Merge branch 'zh/ref-filter-atom-type'
The code to handle the "--format" option in "for-each-ref" and friends made too many string comparisons on %(atom)s used in the format string, which has been corrected by converting them into enum when the format string is parsed. * zh/ref-filter-atom-type: ref-filter: introduce enum atom_type ref-filter: add objectsize to used_atom
This commit is contained in:
commit
289af16300
214
ref-filter.c
214
ref-filter.c
@ -108,6 +108,56 @@ static struct ref_to_worktree_map {
|
||||
struct worktree **worktrees;
|
||||
} ref_to_worktree_map;
|
||||
|
||||
/*
|
||||
* The enum atom_type is used as the index of valid_atom array.
|
||||
* In the atom parsing stage, it will be passed to used_atom.atom_type
|
||||
* as the identifier of the atom type. We can check the type of used_atom
|
||||
* entry by `if (used_atom[i].atom_type == ATOM_*)`.
|
||||
*/
|
||||
enum atom_type {
|
||||
ATOM_REFNAME,
|
||||
ATOM_OBJECTTYPE,
|
||||
ATOM_OBJECTSIZE,
|
||||
ATOM_OBJECTNAME,
|
||||
ATOM_DELTABASE,
|
||||
ATOM_TREE,
|
||||
ATOM_PARENT,
|
||||
ATOM_NUMPARENT,
|
||||
ATOM_OBJECT,
|
||||
ATOM_TYPE,
|
||||
ATOM_TAG,
|
||||
ATOM_AUTHOR,
|
||||
ATOM_AUTHORNAME,
|
||||
ATOM_AUTHOREMAIL,
|
||||
ATOM_AUTHORDATE,
|
||||
ATOM_COMMITTER,
|
||||
ATOM_COMMITTERNAME,
|
||||
ATOM_COMMITTEREMAIL,
|
||||
ATOM_COMMITTERDATE,
|
||||
ATOM_TAGGER,
|
||||
ATOM_TAGGERNAME,
|
||||
ATOM_TAGGEREMAIL,
|
||||
ATOM_TAGGERDATE,
|
||||
ATOM_CREATOR,
|
||||
ATOM_CREATORDATE,
|
||||
ATOM_SUBJECT,
|
||||
ATOM_BODY,
|
||||
ATOM_TRAILERS,
|
||||
ATOM_CONTENTS,
|
||||
ATOM_UPSTREAM,
|
||||
ATOM_PUSH,
|
||||
ATOM_SYMREF,
|
||||
ATOM_FLAG,
|
||||
ATOM_HEAD,
|
||||
ATOM_COLOR,
|
||||
ATOM_WORKTREEPATH,
|
||||
ATOM_ALIGN,
|
||||
ATOM_END,
|
||||
ATOM_IF,
|
||||
ATOM_THEN,
|
||||
ATOM_ELSE,
|
||||
};
|
||||
|
||||
/*
|
||||
* An atom is a valid field atom listed below, possibly prefixed with
|
||||
* a "*" to denote deref_tag().
|
||||
@ -119,6 +169,7 @@ static struct ref_to_worktree_map {
|
||||
* array.
|
||||
*/
|
||||
static struct used_atom {
|
||||
enum atom_type atom_type;
|
||||
const char *name;
|
||||
cmp_type type;
|
||||
info_source source;
|
||||
@ -146,6 +197,9 @@ static struct used_atom {
|
||||
enum { O_FULL, O_LENGTH, O_SHORT } option;
|
||||
unsigned int length;
|
||||
} oid;
|
||||
struct {
|
||||
enum { O_SIZE, O_SIZE_DISK } option;
|
||||
} objectsize;
|
||||
struct email_option {
|
||||
enum { EO_RAW, EO_TRIM, EO_LOCALPART } option;
|
||||
} email_option;
|
||||
@ -269,11 +323,13 @@ static int objectsize_atom_parser(const struct ref_format *format, struct used_a
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg) {
|
||||
atom->u.objectsize.option = O_SIZE;
|
||||
if (*atom->name == '*')
|
||||
oi_deref.info.sizep = &oi_deref.size;
|
||||
else
|
||||
oi.info.sizep = &oi.size;
|
||||
} else if (!strcmp(arg, "disk")) {
|
||||
atom->u.objectsize.option = O_SIZE_DISK;
|
||||
if (*atom->name == '*')
|
||||
oi_deref.info.disk_sizep = &oi_deref.disk_size;
|
||||
else
|
||||
@ -501,47 +557,47 @@ static struct {
|
||||
int (*parser)(const struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err);
|
||||
} valid_atom[] = {
|
||||
{ "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
{ "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
|
||||
{ "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
|
||||
{ "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
|
||||
{ "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
|
||||
{ "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
|
||||
{ "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
|
||||
{ "numparent", SOURCE_OBJ, FIELD_ULONG },
|
||||
{ "object", SOURCE_OBJ },
|
||||
{ "type", SOURCE_OBJ },
|
||||
{ "tag", SOURCE_OBJ },
|
||||
{ "author", SOURCE_OBJ },
|
||||
{ "authorname", SOURCE_OBJ },
|
||||
{ "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
{ "authordate", SOURCE_OBJ, FIELD_TIME },
|
||||
{ "committer", SOURCE_OBJ },
|
||||
{ "committername", SOURCE_OBJ },
|
||||
{ "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
{ "committerdate", SOURCE_OBJ, FIELD_TIME },
|
||||
{ "tagger", SOURCE_OBJ },
|
||||
{ "taggername", SOURCE_OBJ },
|
||||
{ "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
{ "taggerdate", SOURCE_OBJ, FIELD_TIME },
|
||||
{ "creator", SOURCE_OBJ },
|
||||
{ "creatordate", SOURCE_OBJ, FIELD_TIME },
|
||||
{ "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
|
||||
{ "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
|
||||
{ "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
|
||||
{ "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
|
||||
{ "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
{ "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
{ "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
{ "flag", SOURCE_NONE },
|
||||
{ "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
|
||||
{ "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
|
||||
{ "worktreepath", SOURCE_NONE },
|
||||
{ "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
|
||||
{ "end", SOURCE_NONE },
|
||||
{ "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
|
||||
{ "then", SOURCE_NONE },
|
||||
{ "else", SOURCE_NONE },
|
||||
[ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
[ATOM_OBJECTTYPE] = { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
|
||||
[ATOM_OBJECTSIZE] = { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
|
||||
[ATOM_OBJECTNAME] = { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
|
||||
[ATOM_DELTABASE] = { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
|
||||
[ATOM_TREE] = { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
|
||||
[ATOM_PARENT] = { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
|
||||
[ATOM_NUMPARENT] = { "numparent", SOURCE_OBJ, FIELD_ULONG },
|
||||
[ATOM_OBJECT] = { "object", SOURCE_OBJ },
|
||||
[ATOM_TYPE] = { "type", SOURCE_OBJ },
|
||||
[ATOM_TAG] = { "tag", SOURCE_OBJ },
|
||||
[ATOM_AUTHOR] = { "author", SOURCE_OBJ },
|
||||
[ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ },
|
||||
[ATOM_AUTHOREMAIL] = { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
[ATOM_AUTHORDATE] = { "authordate", SOURCE_OBJ, FIELD_TIME },
|
||||
[ATOM_COMMITTER] = { "committer", SOURCE_OBJ },
|
||||
[ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ },
|
||||
[ATOM_COMMITTEREMAIL] = { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
[ATOM_COMMITTERDATE] = { "committerdate", SOURCE_OBJ, FIELD_TIME },
|
||||
[ATOM_TAGGER] = { "tagger", SOURCE_OBJ },
|
||||
[ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ },
|
||||
[ATOM_TAGGEREMAIL] = { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
|
||||
[ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME },
|
||||
[ATOM_CREATOR] = { "creator", SOURCE_OBJ },
|
||||
[ATOM_CREATORDATE] = { "creatordate", SOURCE_OBJ, FIELD_TIME },
|
||||
[ATOM_SUBJECT] = { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
|
||||
[ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
|
||||
[ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
|
||||
[ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
|
||||
[ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
[ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
[ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
[ATOM_FLAG] = { "flag", SOURCE_NONE },
|
||||
[ATOM_HEAD] = { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
|
||||
[ATOM_COLOR] = { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
|
||||
[ATOM_WORKTREEPATH] = { "worktreepath", SOURCE_NONE },
|
||||
[ATOM_ALIGN] = { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
|
||||
[ATOM_END] = { "end", SOURCE_NONE },
|
||||
[ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
|
||||
[ATOM_THEN] = { "then", SOURCE_NONE },
|
||||
[ATOM_ELSE] = { "else", SOURCE_NONE },
|
||||
/*
|
||||
* Please update $__git_ref_fieldlist in git-completion.bash
|
||||
* when you add new atoms
|
||||
@ -623,6 +679,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
|
||||
at = used_atom_cnt;
|
||||
used_atom_cnt++;
|
||||
REALLOC_ARRAY(used_atom, used_atom_cnt);
|
||||
used_atom[at].atom_type = i;
|
||||
used_atom[at].name = xmemdupz(atom, ep - atom);
|
||||
used_atom[at].type = valid_atom[i].cmp_type;
|
||||
used_atom[at].source = valid_atom[i].source;
|
||||
@ -647,7 +704,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
|
||||
return -1;
|
||||
if (*atom == '*')
|
||||
need_tagged = 1;
|
||||
if (!strcmp(valid_atom[i].name, "symref"))
|
||||
if (i == ATOM_SYMREF)
|
||||
need_symref = 1;
|
||||
return at;
|
||||
}
|
||||
@ -960,22 +1017,25 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
|
||||
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
const char *name = used_atom[i].name;
|
||||
enum atom_type atom_type = used_atom[i].atom_type;
|
||||
struct atom_value *v = &val[i];
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
name++;
|
||||
if (!strcmp(name, "objecttype"))
|
||||
if (atom_type == ATOM_OBJECTTYPE)
|
||||
v->s = xstrdup(type_name(oi->type));
|
||||
else if (!strcmp(name, "objectsize:disk")) {
|
||||
v->value = oi->disk_size;
|
||||
v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size);
|
||||
} else if (!strcmp(name, "objectsize")) {
|
||||
v->value = oi->size;
|
||||
v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
|
||||
} else if (!strcmp(name, "deltabase"))
|
||||
else if (atom_type == ATOM_OBJECTSIZE) {
|
||||
if (used_atom[i].u.objectsize.option == O_SIZE_DISK) {
|
||||
v->value = oi->disk_size;
|
||||
v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size);
|
||||
} else if (used_atom[i].u.objectsize.option == O_SIZE) {
|
||||
v->value = oi->size;
|
||||
v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
|
||||
}
|
||||
} else if (atom_type == ATOM_DELTABASE)
|
||||
v->s = xstrdup(oid_to_hex(&oi->delta_base_oid));
|
||||
else if (deref)
|
||||
else if (atom_type == ATOM_OBJECTNAME && deref)
|
||||
grab_oid(name, "objectname", &oi->oid, v, &used_atom[i]);
|
||||
}
|
||||
}
|
||||
@ -988,16 +1048,17 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
|
||||
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
const char *name = used_atom[i].name;
|
||||
enum atom_type atom_type = used_atom[i].atom_type;
|
||||
struct atom_value *v = &val[i];
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
name++;
|
||||
if (!strcmp(name, "tag"))
|
||||
if (atom_type == ATOM_TAG)
|
||||
v->s = xstrdup(tag->tag);
|
||||
else if (!strcmp(name, "type") && tag->tagged)
|
||||
else if (atom_type == ATOM_TYPE && tag->tagged)
|
||||
v->s = xstrdup(type_name(tag->tagged->type));
|
||||
else if (!strcmp(name, "object") && tag->tagged)
|
||||
else if (atom_type == ATOM_OBJECT && tag->tagged)
|
||||
v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
|
||||
}
|
||||
}
|
||||
@ -1010,18 +1071,20 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
|
||||
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
const char *name = used_atom[i].name;
|
||||
enum atom_type atom_type = used_atom[i].atom_type;
|
||||
struct atom_value *v = &val[i];
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
name++;
|
||||
if (grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
|
||||
if (atom_type == ATOM_TREE &&
|
||||
grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
|
||||
continue;
|
||||
if (!strcmp(name, "numparent")) {
|
||||
if (atom_type == ATOM_NUMPARENT) {
|
||||
v->value = commit_list_count(commit->parents);
|
||||
v->s = xstrfmt("%lu", (unsigned long)v->value);
|
||||
}
|
||||
else if (starts_with(name, "parent")) {
|
||||
else if (atom_type == ATOM_PARENT) {
|
||||
struct commit_list *parents;
|
||||
struct strbuf s = STRBUF_INIT;
|
||||
for (parents = commit->parents; parents; parents = parents->next) {
|
||||
@ -1201,15 +1264,16 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
|
||||
return;
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
const char *name = used_atom[i].name;
|
||||
enum atom_type atom_type = used_atom[i].atom_type;
|
||||
struct atom_value *v = &val[i];
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
name++;
|
||||
|
||||
if (starts_with(name, "creatordate"))
|
||||
if (atom_type == ATOM_CREATORDATE)
|
||||
grab_date(wholine, v, name);
|
||||
else if (!strcmp(name, "creator"))
|
||||
else if (atom_type == ATOM_CREATOR)
|
||||
v->s = copy_line(wholine);
|
||||
}
|
||||
}
|
||||
@ -1689,6 +1753,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
/* Fill in specials first */
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
struct used_atom *atom = &used_atom[i];
|
||||
enum atom_type atom_type = atom->atom_type;
|
||||
const char *name = used_atom[i].name;
|
||||
struct atom_value *v = &ref->value[i];
|
||||
int deref = 0;
|
||||
@ -1703,18 +1768,18 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
name++;
|
||||
}
|
||||
|
||||
if (starts_with(name, "refname"))
|
||||
if (atom_type == ATOM_REFNAME)
|
||||
refname = get_refname(atom, ref);
|
||||
else if (!strcmp(name, "worktreepath")) {
|
||||
else if (atom_type == ATOM_WORKTREEPATH) {
|
||||
if (ref->kind == FILTER_REFS_BRANCHES)
|
||||
v->s = get_worktree_path(atom, ref);
|
||||
else
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
}
|
||||
else if (starts_with(name, "symref"))
|
||||
else if (atom_type == ATOM_SYMREF)
|
||||
refname = get_symref(atom, ref);
|
||||
else if (starts_with(name, "upstream")) {
|
||||
else if (atom_type == ATOM_UPSTREAM) {
|
||||
const char *branch_name;
|
||||
/* only local branches may have an upstream */
|
||||
if (!skip_prefix(ref->refname, "refs/heads/",
|
||||
@ -1730,7 +1795,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
else
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:")) {
|
||||
} else if (atom_type == ATOM_PUSH && atom->u.remote_ref.push) {
|
||||
const char *branch_name;
|
||||
v->s = xstrdup("");
|
||||
if (!skip_prefix(ref->refname, "refs/heads/",
|
||||
@ -1749,10 +1814,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
free((char *)v->s);
|
||||
fill_remote_ref_details(atom, refname, branch, &v->s);
|
||||
continue;
|
||||
} else if (starts_with(name, "color:")) {
|
||||
} else if (atom_type == ATOM_COLOR) {
|
||||
v->s = xstrdup(atom->u.color);
|
||||
continue;
|
||||
} else if (!strcmp(name, "flag")) {
|
||||
} else if (atom_type == ATOM_FLAG) {
|
||||
char buf[256], *cp = buf;
|
||||
if (ref->flag & REF_ISSYMREF)
|
||||
cp = copy_advance(cp, ",symref");
|
||||
@ -1765,23 +1830,24 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
v->s = xstrdup(buf + 1);
|
||||
}
|
||||
continue;
|
||||
} else if (!deref && grab_oid(name, "objectname", &ref->objectname, v, atom)) {
|
||||
continue;
|
||||
} else if (!strcmp(name, "HEAD")) {
|
||||
} else if (!deref && atom_type == ATOM_OBJECTNAME &&
|
||||
grab_oid(name, "objectname", &ref->objectname, v, atom)) {
|
||||
continue;
|
||||
} else if (atom_type == ATOM_HEAD) {
|
||||
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
|
||||
v->s = xstrdup("*");
|
||||
else
|
||||
v->s = xstrdup(" ");
|
||||
continue;
|
||||
} else if (starts_with(name, "align")) {
|
||||
} else if (atom_type == ATOM_ALIGN) {
|
||||
v->handler = align_atom_handler;
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else if (!strcmp(name, "end")) {
|
||||
} else if (atom_type == ATOM_END) {
|
||||
v->handler = end_atom_handler;
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else if (starts_with(name, "if")) {
|
||||
} else if (atom_type == ATOM_IF) {
|
||||
const char *s;
|
||||
if (skip_prefix(name, "if:", &s))
|
||||
v->s = xstrdup(s);
|
||||
@ -1789,11 +1855,11 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
||||
v->s = xstrdup("");
|
||||
v->handler = if_atom_handler;
|
||||
continue;
|
||||
} else if (!strcmp(name, "then")) {
|
||||
} else if (atom_type == ATOM_THEN) {
|
||||
v->handler = then_atom_handler;
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else if (!strcmp(name, "else")) {
|
||||
} else if (atom_type == ATOM_ELSE) {
|
||||
v->handler = else_atom_handler;
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user