Skip to content

Commit 8fb522c

Browse files
committed
Merge branch 'ot/ref-filter-object-info' into pu
A few atoms like %(objecttype) and %(objectsize) in the format specifier of "for-each-ref --format=<format>" can be filled without getting the full contents of the object, but just with the object header. These cases have been optimzied by calling oid_object_info() API. What's the doneness of this one? * ot/ref-filter-object-info: ref-filter: use oid_object_info() to get object ref-filter: merge get_obj and get_object ref-filter: initialize eaten variable ref-filter: fill empty fields with empty values ref-filter: add info_source to valid_atom
2 parents b37f1ea + aa46a0d commit 8fb522c

File tree

1 file changed

+138
-88
lines changed

1 file changed

+138
-88
lines changed

ref-filter.c

Lines changed: 138 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void setup_ref_filter_porcelain_msg(void)
4343

4444
typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
4545
typedef enum { COMPARE_EQUAL, COMPARE_UNEQUAL, COMPARE_NONE } cmp_status;
46+
typedef enum { SOURCE_NONE = 0, SOURCE_OBJ, SOURCE_OTHER } info_source;
4647

4748
struct align {
4849
align_type position;
@@ -62,6 +63,17 @@ struct refname_atom {
6263
int lstrip, rstrip;
6364
};
6465

66+
static struct expand_data {
67+
struct object_id oid;
68+
enum object_type type;
69+
unsigned long size;
70+
off_t disk_size;
71+
struct object_id delta_base_oid;
72+
void *content;
73+
74+
struct object_info info;
75+
} oi, oi_deref;
76+
6577
/*
6678
* An atom is a valid field atom listed below, possibly prefixed with
6779
* a "*" to denote deref_tag().
@@ -75,6 +87,7 @@ struct refname_atom {
7587
static struct used_atom {
7688
const char *name;
7789
cmp_type type;
90+
info_source source;
7891
union {
7992
char color[COLOR_MAXLEN];
8093
struct align align;
@@ -202,6 +215,30 @@ static int remote_ref_atom_parser(const struct ref_format *format, struct used_a
202215
return 0;
203216
}
204217

218+
static int objecttype_atom_parser(const struct ref_format *format, struct used_atom *atom,
219+
const char *arg, struct strbuf *err)
220+
{
221+
if (arg)
222+
return strbuf_addf_ret(err, -1, _("%%(objecttype) does not take arguments"));
223+
if (*atom->name == '*')
224+
oi_deref.info.typep = &oi_deref.type;
225+
else
226+
oi.info.typep = &oi.type;
227+
return 0;
228+
}
229+
230+
static int objectsize_atom_parser(const struct ref_format *format, struct used_atom *atom,
231+
const char *arg, struct strbuf *err)
232+
{
233+
if (arg)
234+
return strbuf_addf_ret(err, -1, _("%%(objectsize) does not take arguments"));
235+
if (*atom->name == '*')
236+
oi_deref.info.sizep = &oi_deref.size;
237+
else
238+
oi.info.sizep = &oi.size;
239+
return 0;
240+
}
241+
205242
static int body_atom_parser(const struct ref_format *format, struct used_atom *atom,
206243
const char *arg, struct strbuf *err)
207244
{
@@ -382,49 +419,50 @@ static int head_atom_parser(const struct ref_format *format, struct used_atom *a
382419

383420
static struct {
384421
const char *name;
422+
info_source source;
385423
cmp_type cmp_type;
386424
int (*parser)(const struct ref_format *format, struct used_atom *atom,
387425
const char *arg, struct strbuf *err);
388426
} valid_atom[] = {
389-
{ "refname" , FIELD_STR, refname_atom_parser },
390-
{ "objecttype" },
391-
{ "objectsize", FIELD_ULONG },
392-
{ "objectname", FIELD_STR, objectname_atom_parser },
393-
{ "tree" },
394-
{ "parent" },
395-
{ "numparent", FIELD_ULONG },
396-
{ "object" },
397-
{ "type" },
398-
{ "tag" },
399-
{ "author" },
400-
{ "authorname" },
401-
{ "authoremail" },
402-
{ "authordate", FIELD_TIME },
403-
{ "committer" },
404-
{ "committername" },
405-
{ "committeremail" },
406-
{ "committerdate", FIELD_TIME },
407-
{ "tagger" },
408-
{ "taggername" },
409-
{ "taggeremail" },
410-
{ "taggerdate", FIELD_TIME },
411-
{ "creator" },
412-
{ "creatordate", FIELD_TIME },
413-
{ "subject", FIELD_STR, subject_atom_parser },
414-
{ "body", FIELD_STR, body_atom_parser },
415-
{ "trailers", FIELD_STR, trailers_atom_parser },
416-
{ "contents", FIELD_STR, contents_atom_parser },
417-
{ "upstream", FIELD_STR, remote_ref_atom_parser },
418-
{ "push", FIELD_STR, remote_ref_atom_parser },
419-
{ "symref", FIELD_STR, refname_atom_parser },
420-
{ "flag" },
421-
{ "HEAD", FIELD_STR, head_atom_parser },
422-
{ "color", FIELD_STR, color_atom_parser },
423-
{ "align", FIELD_STR, align_atom_parser },
424-
{ "end" },
425-
{ "if", FIELD_STR, if_atom_parser },
426-
{ "then" },
427-
{ "else" },
427+
{ "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
428+
{ "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
429+
{ "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
430+
{ "objectname", SOURCE_OTHER, FIELD_STR, objectname_atom_parser },
431+
{ "tree", SOURCE_OBJ },
432+
{ "parent", SOURCE_OBJ },
433+
{ "numparent", SOURCE_OBJ, FIELD_ULONG },
434+
{ "object", SOURCE_OBJ },
435+
{ "type", SOURCE_OBJ },
436+
{ "tag", SOURCE_OBJ },
437+
{ "author", SOURCE_OBJ },
438+
{ "authorname", SOURCE_OBJ },
439+
{ "authoremail", SOURCE_OBJ },
440+
{ "authordate", SOURCE_OBJ, FIELD_TIME },
441+
{ "committer", SOURCE_OBJ },
442+
{ "committername", SOURCE_OBJ },
443+
{ "committeremail", SOURCE_OBJ },
444+
{ "committerdate", SOURCE_OBJ, FIELD_TIME },
445+
{ "tagger", SOURCE_OBJ },
446+
{ "taggername", SOURCE_OBJ },
447+
{ "taggeremail", SOURCE_OBJ },
448+
{ "taggerdate", SOURCE_OBJ, FIELD_TIME },
449+
{ "creator", SOURCE_OBJ },
450+
{ "creatordate", SOURCE_OBJ, FIELD_TIME },
451+
{ "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
452+
{ "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
453+
{ "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
454+
{ "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
455+
{ "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
456+
{ "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
457+
{ "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
458+
{ "flag", SOURCE_NONE },
459+
{ "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
460+
{ "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
461+
{ "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
462+
{ "end", SOURCE_NONE },
463+
{ "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
464+
{ "then", SOURCE_NONE },
465+
{ "else", SOURCE_NONE },
428466
};
429467

430468
#define REF_FORMATTING_STATE_INIT { 0, NULL }
@@ -500,6 +538,13 @@ static int parse_ref_filter_atom(const struct ref_format *format,
500538
REALLOC_ARRAY(used_atom, used_atom_cnt);
501539
used_atom[at].name = xmemdupz(atom, ep - atom);
502540
used_atom[at].type = valid_atom[i].cmp_type;
541+
used_atom[at].source = valid_atom[i].source;
542+
if (used_atom[at].source == SOURCE_OBJ) {
543+
if (*atom == '*')
544+
oi_deref.info.contentp = &oi_deref.content;
545+
else
546+
oi.info.contentp = &oi.content;
547+
}
503548
if (arg) {
504549
arg = used_atom[at].name + (arg - atom) + 1;
505550
if (!*arg) {
@@ -795,25 +840,6 @@ int verify_ref_format(struct ref_format *format)
795840
return 0;
796841
}
797842

798-
/*
799-
* Given an object name, read the object data and size, and return a
800-
* "struct object". If the object data we are returning is also borrowed
801-
* by the "struct object" representation, set *eaten as well---it is a
802-
* signal from parse_object_buffer to us not to free the buffer.
803-
*/
804-
static void *get_obj(const struct object_id *oid, struct object **obj, unsigned long *sz, int *eaten)
805-
{
806-
enum object_type type;
807-
void *buf = read_object_file(oid, &type, sz);
808-
809-
if (buf)
810-
*obj = parse_object_buffer(the_repository, oid, type, *sz,
811-
buf, eaten);
812-
else
813-
*obj = NULL;
814-
return buf;
815-
}
816-
817843
static int grab_objectname(const char *name, const struct object_id *oid,
818844
struct atom_value *v, struct used_atom *atom)
819845
{
@@ -834,7 +860,7 @@ static int grab_objectname(const char *name, const struct object_id *oid,
834860
}
835861

836862
/* See grab_values */
837-
static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
863+
static void grab_common_values(struct atom_value *val, int deref, struct expand_data *oi)
838864
{
839865
int i;
840866

@@ -846,13 +872,13 @@ static void grab_common_values(struct atom_value *val, int deref, struct object
846872
if (deref)
847873
name++;
848874
if (!strcmp(name, "objecttype"))
849-
v->s = type_name(obj->type);
875+
v->s = type_name(oi->type);
850876
else if (!strcmp(name, "objectsize")) {
851-
v->value = sz;
852-
v->s = xstrfmt("%lu", sz);
877+
v->value = oi->size;
878+
v->s = xstrfmt("%lu", oi->size);
853879
}
854880
else if (deref)
855-
grab_objectname(name, &obj->oid, v, &used_atom[i]);
881+
grab_objectname(name, &oi->oid, v, &used_atom[i]);
856882
}
857883
}
858884

@@ -1211,7 +1237,6 @@ static void fill_missing_values(struct atom_value *val)
12111237
*/
12121238
static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
12131239
{
1214-
grab_common_values(val, deref, obj, buf, sz);
12151240
switch (obj->type) {
12161241
case OBJ_TAG:
12171242
grab_tag_values(val, deref, obj, buf, sz);
@@ -1435,24 +1460,36 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re
14351460
return show_ref(&atom->u.refname, ref->refname);
14361461
}
14371462

1438-
static int get_object(struct ref_array_item *ref, const struct object_id *oid,
1439-
int deref, struct object **obj, struct strbuf *err)
1463+
static int get_object(struct ref_array_item *ref, int deref, struct object **obj,
1464+
struct expand_data *oi, struct strbuf *err)
14401465
{
1441-
int eaten;
1442-
int ret = 0;
1443-
unsigned long size;
1444-
void *buf = get_obj(oid, obj, &size, &eaten);
1445-
if (!buf)
1446-
ret = strbuf_addf_ret(err, -1, _("missing object %s for %s"),
1447-
oid_to_hex(oid), ref->refname);
1448-
else if (!*obj)
1449-
ret = strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
1450-
oid_to_hex(oid), ref->refname);
1451-
else
1452-
grab_values(ref->value, deref, *obj, buf, size);
1466+
/* parse_object_buffer() will set eaten to 0 if free() will be needed */
1467+
int eaten = 1;
1468+
if (oi->info.contentp) {
1469+
/* We need to know that to use parse_object_buffer properly */
1470+
oi->info.sizep = &oi->size;
1471+
oi->info.typep = &oi->type;
1472+
}
1473+
if (oid_object_info_extended(the_repository, &oi->oid, &oi->info,
1474+
OBJECT_INFO_LOOKUP_REPLACE))
1475+
return strbuf_addf_ret(err, -1, _("missing object %s for %s"),
1476+
oid_to_hex(&oi->oid), ref->refname);
1477+
1478+
if (oi->info.contentp) {
1479+
*obj = parse_object_buffer(the_repository, &oi->oid, oi->type, oi->size, oi->content, &eaten);
1480+
if (!obj) {
1481+
if (!eaten)
1482+
free(oi->content);
1483+
return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
1484+
oid_to_hex(&oi->oid), ref->refname);
1485+
}
1486+
grab_values(ref->value, deref, *obj, oi->content, oi->size);
1487+
}
1488+
1489+
grab_common_values(ref->value, deref, oi);
14531490
if (!eaten)
1454-
free(buf);
1455-
return ret;
1491+
free(oi->content);
1492+
return 0;
14561493
}
14571494

14581495
/*
@@ -1462,7 +1499,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
14621499
{
14631500
struct object *obj;
14641501
int i;
1465-
const struct object_id *tagged;
1502+
struct object_info empty = OBJECT_INFO_INIT;
14661503

14671504
ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
14681505

@@ -1496,6 +1533,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
14961533
refname = get_symref(atom, ref);
14971534
else if (starts_with(name, "upstream")) {
14981535
const char *branch_name;
1536+
v->s = "";
14991537
/* only local branches may have an upstream */
15001538
if (!skip_prefix(ref->refname, "refs/heads/",
15011539
&branch_name))
@@ -1508,6 +1546,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
15081546
continue;
15091547
} else if (atom->u.remote_ref.push) {
15101548
const char *branch_name;
1549+
v->s = "";
15111550
if (!skip_prefix(ref->refname, "refs/heads/",
15121551
&branch_name))
15131552
continue;
@@ -1548,22 +1587,26 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
15481587
continue;
15491588
} else if (starts_with(name, "align")) {
15501589
v->handler = align_atom_handler;
1590+
v->s = "";
15511591
continue;
15521592
} else if (!strcmp(name, "end")) {
15531593
v->handler = end_atom_handler;
1594+
v->s = "";
15541595
continue;
15551596
} else if (starts_with(name, "if")) {
15561597
const char *s;
1557-
1598+
v->s = "";
15581599
if (skip_prefix(name, "if:", &s))
15591600
v->s = xstrdup(s);
15601601
v->handler = if_atom_handler;
15611602
continue;
15621603
} else if (!strcmp(name, "then")) {
15631604
v->handler = then_atom_handler;
1605+
v->s = "";
15641606
continue;
15651607
} else if (!strcmp(name, "else")) {
15661608
v->handler = else_atom_handler;
1609+
v->s = "";
15671610
continue;
15681611
} else
15691612
continue;
@@ -1576,13 +1619,20 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
15761619

15771620
for (i = 0; i < used_atom_cnt; i++) {
15781621
struct atom_value *v = &ref->value[i];
1579-
if (v->s == NULL)
1580-
break;
1622+
if (v->s == NULL && used_atom[i].source == SOURCE_NONE)
1623+
return strbuf_addf_ret(err, -1, _("missing object %s for %s"),
1624+
oid_to_hex(&ref->objectname), ref->refname);
15811625
}
1582-
if (used_atom_cnt <= i)
1626+
1627+
if (need_tagged)
1628+
oi.info.contentp = &oi.content;
1629+
if (!memcmp(&oi.info, &empty, sizeof(empty)) &&
1630+
!memcmp(&oi_deref.info, &empty, sizeof(empty)))
15831631
return 0;
15841632

1585-
if (get_object(ref, &ref->objectname, 0, &obj, err))
1633+
1634+
oi.oid = ref->objectname;
1635+
if (get_object(ref, 0, &obj, &oi, err))
15861636
return -1;
15871637

15881638
/*
@@ -1596,15 +1646,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
15961646
* If it is a tag object, see if we use a value that derefs
15971647
* the object, and if we do grab the object it refers to.
15981648
*/
1599-
tagged = &((struct tag *)obj)->tagged->oid;
1649+
oi_deref.oid = ((struct tag *)obj)->tagged->oid;
16001650

16011651
/*
16021652
* NEEDSWORK: This derefs tag only once, which
16031653
* is good to deal with chains of trust, but
16041654
* is not consistent with what deref_tag() does
16051655
* which peels the onion to the core.
16061656
*/
1607-
return get_object(ref, tagged, 1, &obj, err);
1657+
return get_object(ref, 1, &obj, &oi_deref, err);
16081658
}
16091659

16101660
/*

0 commit comments

Comments
 (0)