Skip to content

Commit 289af16

Browse files
committed
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
2 parents 211eca0 + 1197f1a commit 289af16

File tree

1 file changed

+140
-74
lines changed

1 file changed

+140
-74
lines changed

ref-filter.c

Lines changed: 140 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,56 @@ static struct ref_to_worktree_map {
108108
struct worktree **worktrees;
109109
} ref_to_worktree_map;
110110

111+
/*
112+
* The enum atom_type is used as the index of valid_atom array.
113+
* In the atom parsing stage, it will be passed to used_atom.atom_type
114+
* as the identifier of the atom type. We can check the type of used_atom
115+
* entry by `if (used_atom[i].atom_type == ATOM_*)`.
116+
*/
117+
enum atom_type {
118+
ATOM_REFNAME,
119+
ATOM_OBJECTTYPE,
120+
ATOM_OBJECTSIZE,
121+
ATOM_OBJECTNAME,
122+
ATOM_DELTABASE,
123+
ATOM_TREE,
124+
ATOM_PARENT,
125+
ATOM_NUMPARENT,
126+
ATOM_OBJECT,
127+
ATOM_TYPE,
128+
ATOM_TAG,
129+
ATOM_AUTHOR,
130+
ATOM_AUTHORNAME,
131+
ATOM_AUTHOREMAIL,
132+
ATOM_AUTHORDATE,
133+
ATOM_COMMITTER,
134+
ATOM_COMMITTERNAME,
135+
ATOM_COMMITTEREMAIL,
136+
ATOM_COMMITTERDATE,
137+
ATOM_TAGGER,
138+
ATOM_TAGGERNAME,
139+
ATOM_TAGGEREMAIL,
140+
ATOM_TAGGERDATE,
141+
ATOM_CREATOR,
142+
ATOM_CREATORDATE,
143+
ATOM_SUBJECT,
144+
ATOM_BODY,
145+
ATOM_TRAILERS,
146+
ATOM_CONTENTS,
147+
ATOM_UPSTREAM,
148+
ATOM_PUSH,
149+
ATOM_SYMREF,
150+
ATOM_FLAG,
151+
ATOM_HEAD,
152+
ATOM_COLOR,
153+
ATOM_WORKTREEPATH,
154+
ATOM_ALIGN,
155+
ATOM_END,
156+
ATOM_IF,
157+
ATOM_THEN,
158+
ATOM_ELSE,
159+
};
160+
111161
/*
112162
* An atom is a valid field atom listed below, possibly prefixed with
113163
* a "*" to denote deref_tag().
@@ -119,6 +169,7 @@ static struct ref_to_worktree_map {
119169
* array.
120170
*/
121171
static struct used_atom {
172+
enum atom_type atom_type;
122173
const char *name;
123174
cmp_type type;
124175
info_source source;
@@ -146,6 +197,9 @@ static struct used_atom {
146197
enum { O_FULL, O_LENGTH, O_SHORT } option;
147198
unsigned int length;
148199
} oid;
200+
struct {
201+
enum { O_SIZE, O_SIZE_DISK } option;
202+
} objectsize;
149203
struct email_option {
150204
enum { EO_RAW, EO_TRIM, EO_LOCALPART } option;
151205
} email_option;
@@ -269,11 +323,13 @@ static int objectsize_atom_parser(const struct ref_format *format, struct used_a
269323
const char *arg, struct strbuf *err)
270324
{
271325
if (!arg) {
326+
atom->u.objectsize.option = O_SIZE;
272327
if (*atom->name == '*')
273328
oi_deref.info.sizep = &oi_deref.size;
274329
else
275330
oi.info.sizep = &oi.size;
276331
} else if (!strcmp(arg, "disk")) {
332+
atom->u.objectsize.option = O_SIZE_DISK;
277333
if (*atom->name == '*')
278334
oi_deref.info.disk_sizep = &oi_deref.disk_size;
279335
else
@@ -501,47 +557,47 @@ static struct {
501557
int (*parser)(const struct ref_format *format, struct used_atom *atom,
502558
const char *arg, struct strbuf *err);
503559
} valid_atom[] = {
504-
{ "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
505-
{ "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
506-
{ "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
507-
{ "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
508-
{ "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
509-
{ "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
510-
{ "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
511-
{ "numparent", SOURCE_OBJ, FIELD_ULONG },
512-
{ "object", SOURCE_OBJ },
513-
{ "type", SOURCE_OBJ },
514-
{ "tag", SOURCE_OBJ },
515-
{ "author", SOURCE_OBJ },
516-
{ "authorname", SOURCE_OBJ },
517-
{ "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
518-
{ "authordate", SOURCE_OBJ, FIELD_TIME },
519-
{ "committer", SOURCE_OBJ },
520-
{ "committername", SOURCE_OBJ },
521-
{ "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
522-
{ "committerdate", SOURCE_OBJ, FIELD_TIME },
523-
{ "tagger", SOURCE_OBJ },
524-
{ "taggername", SOURCE_OBJ },
525-
{ "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
526-
{ "taggerdate", SOURCE_OBJ, FIELD_TIME },
527-
{ "creator", SOURCE_OBJ },
528-
{ "creatordate", SOURCE_OBJ, FIELD_TIME },
529-
{ "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
530-
{ "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
531-
{ "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
532-
{ "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
533-
{ "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
534-
{ "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
535-
{ "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
536-
{ "flag", SOURCE_NONE },
537-
{ "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
538-
{ "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
539-
{ "worktreepath", SOURCE_NONE },
540-
{ "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
541-
{ "end", SOURCE_NONE },
542-
{ "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
543-
{ "then", SOURCE_NONE },
544-
{ "else", SOURCE_NONE },
560+
[ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
561+
[ATOM_OBJECTTYPE] = { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
562+
[ATOM_OBJECTSIZE] = { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
563+
[ATOM_OBJECTNAME] = { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
564+
[ATOM_DELTABASE] = { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
565+
[ATOM_TREE] = { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
566+
[ATOM_PARENT] = { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
567+
[ATOM_NUMPARENT] = { "numparent", SOURCE_OBJ, FIELD_ULONG },
568+
[ATOM_OBJECT] = { "object", SOURCE_OBJ },
569+
[ATOM_TYPE] = { "type", SOURCE_OBJ },
570+
[ATOM_TAG] = { "tag", SOURCE_OBJ },
571+
[ATOM_AUTHOR] = { "author", SOURCE_OBJ },
572+
[ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ },
573+
[ATOM_AUTHOREMAIL] = { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
574+
[ATOM_AUTHORDATE] = { "authordate", SOURCE_OBJ, FIELD_TIME },
575+
[ATOM_COMMITTER] = { "committer", SOURCE_OBJ },
576+
[ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ },
577+
[ATOM_COMMITTEREMAIL] = { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
578+
[ATOM_COMMITTERDATE] = { "committerdate", SOURCE_OBJ, FIELD_TIME },
579+
[ATOM_TAGGER] = { "tagger", SOURCE_OBJ },
580+
[ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ },
581+
[ATOM_TAGGEREMAIL] = { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
582+
[ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME },
583+
[ATOM_CREATOR] = { "creator", SOURCE_OBJ },
584+
[ATOM_CREATORDATE] = { "creatordate", SOURCE_OBJ, FIELD_TIME },
585+
[ATOM_SUBJECT] = { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
586+
[ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
587+
[ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
588+
[ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
589+
[ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
590+
[ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
591+
[ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
592+
[ATOM_FLAG] = { "flag", SOURCE_NONE },
593+
[ATOM_HEAD] = { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
594+
[ATOM_COLOR] = { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
595+
[ATOM_WORKTREEPATH] = { "worktreepath", SOURCE_NONE },
596+
[ATOM_ALIGN] = { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
597+
[ATOM_END] = { "end", SOURCE_NONE },
598+
[ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
599+
[ATOM_THEN] = { "then", SOURCE_NONE },
600+
[ATOM_ELSE] = { "else", SOURCE_NONE },
545601
/*
546602
* Please update $__git_ref_fieldlist in git-completion.bash
547603
* when you add new atoms
@@ -623,6 +679,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
623679
at = used_atom_cnt;
624680
used_atom_cnt++;
625681
REALLOC_ARRAY(used_atom, used_atom_cnt);
682+
used_atom[at].atom_type = i;
626683
used_atom[at].name = xmemdupz(atom, ep - atom);
627684
used_atom[at].type = valid_atom[i].cmp_type;
628685
used_atom[at].source = valid_atom[i].source;
@@ -647,7 +704,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
647704
return -1;
648705
if (*atom == '*')
649706
need_tagged = 1;
650-
if (!strcmp(valid_atom[i].name, "symref"))
707+
if (i == ATOM_SYMREF)
651708
need_symref = 1;
652709
return at;
653710
}
@@ -960,22 +1017,25 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
9601017

9611018
for (i = 0; i < used_atom_cnt; i++) {
9621019
const char *name = used_atom[i].name;
1020+
enum atom_type atom_type = used_atom[i].atom_type;
9631021
struct atom_value *v = &val[i];
9641022
if (!!deref != (*name == '*'))
9651023
continue;
9661024
if (deref)
9671025
name++;
968-
if (!strcmp(name, "objecttype"))
1026+
if (atom_type == ATOM_OBJECTTYPE)
9691027
v->s = xstrdup(type_name(oi->type));
970-
else if (!strcmp(name, "objectsize:disk")) {
971-
v->value = oi->disk_size;
972-
v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size);
973-
} else if (!strcmp(name, "objectsize")) {
974-
v->value = oi->size;
975-
v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
976-
} else if (!strcmp(name, "deltabase"))
1028+
else if (atom_type == ATOM_OBJECTSIZE) {
1029+
if (used_atom[i].u.objectsize.option == O_SIZE_DISK) {
1030+
v->value = oi->disk_size;
1031+
v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size);
1032+
} else if (used_atom[i].u.objectsize.option == O_SIZE) {
1033+
v->value = oi->size;
1034+
v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
1035+
}
1036+
} else if (atom_type == ATOM_DELTABASE)
9771037
v->s = xstrdup(oid_to_hex(&oi->delta_base_oid));
978-
else if (deref)
1038+
else if (atom_type == ATOM_OBJECTNAME && deref)
9791039
grab_oid(name, "objectname", &oi->oid, v, &used_atom[i]);
9801040
}
9811041
}
@@ -988,16 +1048,17 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
9881048

9891049
for (i = 0; i < used_atom_cnt; i++) {
9901050
const char *name = used_atom[i].name;
1051+
enum atom_type atom_type = used_atom[i].atom_type;
9911052
struct atom_value *v = &val[i];
9921053
if (!!deref != (*name == '*'))
9931054
continue;
9941055
if (deref)
9951056
name++;
996-
if (!strcmp(name, "tag"))
1057+
if (atom_type == ATOM_TAG)
9971058
v->s = xstrdup(tag->tag);
998-
else if (!strcmp(name, "type") && tag->tagged)
1059+
else if (atom_type == ATOM_TYPE && tag->tagged)
9991060
v->s = xstrdup(type_name(tag->tagged->type));
1000-
else if (!strcmp(name, "object") && tag->tagged)
1061+
else if (atom_type == ATOM_OBJECT && tag->tagged)
10011062
v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
10021063
}
10031064
}
@@ -1010,18 +1071,20 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
10101071

10111072
for (i = 0; i < used_atom_cnt; i++) {
10121073
const char *name = used_atom[i].name;
1074+
enum atom_type atom_type = used_atom[i].atom_type;
10131075
struct atom_value *v = &val[i];
10141076
if (!!deref != (*name == '*'))
10151077
continue;
10161078
if (deref)
10171079
name++;
1018-
if (grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
1080+
if (atom_type == ATOM_TREE &&
1081+
grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
10191082
continue;
1020-
if (!strcmp(name, "numparent")) {
1083+
if (atom_type == ATOM_NUMPARENT) {
10211084
v->value = commit_list_count(commit->parents);
10221085
v->s = xstrfmt("%lu", (unsigned long)v->value);
10231086
}
1024-
else if (starts_with(name, "parent")) {
1087+
else if (atom_type == ATOM_PARENT) {
10251088
struct commit_list *parents;
10261089
struct strbuf s = STRBUF_INIT;
10271090
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
12011264
return;
12021265
for (i = 0; i < used_atom_cnt; i++) {
12031266
const char *name = used_atom[i].name;
1267+
enum atom_type atom_type = used_atom[i].atom_type;
12041268
struct atom_value *v = &val[i];
12051269
if (!!deref != (*name == '*'))
12061270
continue;
12071271
if (deref)
12081272
name++;
12091273

1210-
if (starts_with(name, "creatordate"))
1274+
if (atom_type == ATOM_CREATORDATE)
12111275
grab_date(wholine, v, name);
1212-
else if (!strcmp(name, "creator"))
1276+
else if (atom_type == ATOM_CREATOR)
12131277
v->s = copy_line(wholine);
12141278
}
12151279
}
@@ -1689,6 +1753,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
16891753
/* Fill in specials first */
16901754
for (i = 0; i < used_atom_cnt; i++) {
16911755
struct used_atom *atom = &used_atom[i];
1756+
enum atom_type atom_type = atom->atom_type;
16921757
const char *name = used_atom[i].name;
16931758
struct atom_value *v = &ref->value[i];
16941759
int deref = 0;
@@ -1703,18 +1768,18 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
17031768
name++;
17041769
}
17051770

1706-
if (starts_with(name, "refname"))
1771+
if (atom_type == ATOM_REFNAME)
17071772
refname = get_refname(atom, ref);
1708-
else if (!strcmp(name, "worktreepath")) {
1773+
else if (atom_type == ATOM_WORKTREEPATH) {
17091774
if (ref->kind == FILTER_REFS_BRANCHES)
17101775
v->s = get_worktree_path(atom, ref);
17111776
else
17121777
v->s = xstrdup("");
17131778
continue;
17141779
}
1715-
else if (starts_with(name, "symref"))
1780+
else if (atom_type == ATOM_SYMREF)
17161781
refname = get_symref(atom, ref);
1717-
else if (starts_with(name, "upstream")) {
1782+
else if (atom_type == ATOM_UPSTREAM) {
17181783
const char *branch_name;
17191784
/* only local branches may have an upstream */
17201785
if (!skip_prefix(ref->refname, "refs/heads/",
@@ -1730,7 +1795,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
17301795
else
17311796
v->s = xstrdup("");
17321797
continue;
1733-
} else if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:")) {
1798+
} else if (atom_type == ATOM_PUSH && atom->u.remote_ref.push) {
17341799
const char *branch_name;
17351800
v->s = xstrdup("");
17361801
if (!skip_prefix(ref->refname, "refs/heads/",
@@ -1749,10 +1814,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
17491814
free((char *)v->s);
17501815
fill_remote_ref_details(atom, refname, branch, &v->s);
17511816
continue;
1752-
} else if (starts_with(name, "color:")) {
1817+
} else if (atom_type == ATOM_COLOR) {
17531818
v->s = xstrdup(atom->u.color);
17541819
continue;
1755-
} else if (!strcmp(name, "flag")) {
1820+
} else if (atom_type == ATOM_FLAG) {
17561821
char buf[256], *cp = buf;
17571822
if (ref->flag & REF_ISSYMREF)
17581823
cp = copy_advance(cp, ",symref");
@@ -1765,35 +1830,36 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
17651830
v->s = xstrdup(buf + 1);
17661831
}
17671832
continue;
1768-
} else if (!deref && grab_oid(name, "objectname", &ref->objectname, v, atom)) {
1769-
continue;
1770-
} else if (!strcmp(name, "HEAD")) {
1833+
} else if (!deref && atom_type == ATOM_OBJECTNAME &&
1834+
grab_oid(name, "objectname", &ref->objectname, v, atom)) {
1835+
continue;
1836+
} else if (atom_type == ATOM_HEAD) {
17711837
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
17721838
v->s = xstrdup("*");
17731839
else
17741840
v->s = xstrdup(" ");
17751841
continue;
1776-
} else if (starts_with(name, "align")) {
1842+
} else if (atom_type == ATOM_ALIGN) {
17771843
v->handler = align_atom_handler;
17781844
v->s = xstrdup("");
17791845
continue;
1780-
} else if (!strcmp(name, "end")) {
1846+
} else if (atom_type == ATOM_END) {
17811847
v->handler = end_atom_handler;
17821848
v->s = xstrdup("");
17831849
continue;
1784-
} else if (starts_with(name, "if")) {
1850+
} else if (atom_type == ATOM_IF) {
17851851
const char *s;
17861852
if (skip_prefix(name, "if:", &s))
17871853
v->s = xstrdup(s);
17881854
else
17891855
v->s = xstrdup("");
17901856
v->handler = if_atom_handler;
17911857
continue;
1792-
} else if (!strcmp(name, "then")) {
1858+
} else if (atom_type == ATOM_THEN) {
17931859
v->handler = then_atom_handler;
17941860
v->s = xstrdup("");
17951861
continue;
1796-
} else if (!strcmp(name, "else")) {
1862+
} else if (atom_type == ATOM_ELSE) {
17971863
v->handler = else_atom_handler;
17981864
v->s = xstrdup("");
17991865
continue;

0 commit comments

Comments
 (0)