15 #define QUOTE_PYTHON 3
18 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
22 unsigned long ul; /* used for sorting when not FIELD_STR */
26 struct ref_sort *next;
27 int atom; /* index into used_atom array */
33 unsigned char objectname[20];
34 struct atom_value *value;
43 { "objectsize", FIELD_ULONG },
47 { "numparent", FIELD_ULONG },
54 { "authordate", FIELD_TIME },
58 { "committerdate", FIELD_TIME },
62 { "taggerdate", FIELD_TIME },
64 { "creatordate", FIELD_TIME },
71 * An atom is a valid field atom listed above, possibly prefixed with
72 * a "*" to denote deref_tag().
74 * We parse given format string and sort specifiers, and make a list
75 * of properties that we need to extract out of objects. refinfo
76 * structure will hold an array of values extracted that can be
77 * indexed with the "atom number", which is an index into this
80 static const char **used_atom;
81 static cmp_type *used_atom_type;
82 static int used_atom_cnt, sort_atom_limit, need_tagged;
85 * Used to parse format string and sort specifiers
87 static int parse_atom(const char *atom, const char *ep)
94 if (*sp == '*' && sp < ep)
97 die("malformed field name: %.*s", (int)(ep-atom), atom);
99 /* Do we have the atom already used elsewhere? */
100 for (i = 0; i < used_atom_cnt; i++) {
101 int len = strlen(used_atom[i]);
102 if (len == ep - atom && !memcmp(used_atom[i], atom, len))
106 /* Is the atom a valid one? */
107 for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
108 int len = strlen(valid_atom[i].name);
110 * If the atom name has a colon, strip it and everything after
111 * it off - it specifies the format for this entry, and
112 * shouldn't be used for checking against the valid_atom
115 const char *formatp = strchr(sp, ':');
116 if (!formatp || ep < formatp)
118 if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
122 if (ARRAY_SIZE(valid_atom) <= i)
123 die("unknown field name: %.*s", (int)(ep-atom), atom);
125 /* Add it in, including the deref prefix */
128 used_atom = xrealloc(used_atom,
129 (sizeof *used_atom) * used_atom_cnt);
130 used_atom_type = xrealloc(used_atom_type,
131 (sizeof(*used_atom_type) * used_atom_cnt));
132 n = xmalloc(ep - atom + 1);
133 memcpy(n, atom, ep - atom);
136 used_atom_type[at] = valid_atom[i].cmp_type;
141 * In a format string, find the next occurrence of %(atom).
143 static const char *find_next(const char *cp)
147 /* %( is the start of an atom;
148 * %% is a quoted per-cent.
152 else if (cp[1] == '%')
153 cp++; /* skip over two % */
154 /* otherwise this is a singleton, literal % */
162 * Make sure the format string is well formed, and parse out
165 static void verify_format(const char *format)
168 for (cp = format; *cp && (sp = find_next(cp)); ) {
169 const char *ep = strchr(sp, ')');
171 die("malformatted format string %s", sp);
172 /* sp points at "%(" and ep points at the closing ")" */
173 parse_atom(sp + 2, ep);
179 * Given an object name, read the object data and size, and return a
180 * "struct object". If the object data we are returning is also borrowed
181 * by the "struct object" representation, set *eaten as well---it is a
182 * signal from parse_object_buffer to us not to free the buffer.
184 static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
186 enum object_type type;
187 void *buf = read_sha1_file(sha1, &type, sz);
190 *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
196 /* See grab_values */
197 static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
201 for (i = 0; i < used_atom_cnt; i++) {
202 const char *name = used_atom[i];
203 struct atom_value *v = &val[i];
204 if (!!deref != (*name == '*'))
208 if (!strcmp(name, "objecttype"))
209 v->s = typename(obj->type);
210 else if (!strcmp(name, "objectsize")) {
211 char *s = xmalloc(40);
212 sprintf(s, "%lu", sz);
216 else if (!strcmp(name, "objectname")) {
217 char *s = xmalloc(41);
218 strcpy(s, sha1_to_hex(obj->sha1));
224 /* See grab_values */
225 static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
228 struct tag *tag = (struct tag *) obj;
230 for (i = 0; i < used_atom_cnt; i++) {
231 const char *name = used_atom[i];
232 struct atom_value *v = &val[i];
233 if (!!deref != (*name == '*'))
237 if (!strcmp(name, "tag"))
242 static int num_parents(struct commit *commit)
244 struct commit_list *parents;
247 for (i = 0, parents = commit->parents;
249 parents = parents->next)
254 /* See grab_values */
255 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
258 struct commit *commit = (struct commit *) obj;
260 for (i = 0; i < used_atom_cnt; i++) {
261 const char *name = used_atom[i];
262 struct atom_value *v = &val[i];
263 if (!!deref != (*name == '*'))
267 if (!strcmp(name, "tree")) {
268 char *s = xmalloc(41);
269 strcpy(s, sha1_to_hex(commit->tree->object.sha1));
272 if (!strcmp(name, "numparent")) {
273 char *s = xmalloc(40);
274 v->ul = num_parents(commit);
275 sprintf(s, "%lu", v->ul);
278 else if (!strcmp(name, "parent")) {
279 int num = num_parents(commit);
281 struct commit_list *parents;
282 char *s = xmalloc(41 * num + 1);
284 for (i = 0, parents = commit->parents;
286 parents = parents->next, i = i + 41) {
287 struct commit *parent = parents->item;
288 strcpy(s+i, sha1_to_hex(parent->object.sha1));
298 static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
302 if (!strncmp(buf, who, wholen) &&
304 return buf + wholen + 1;
305 eol = strchr(buf, '\n');
310 return ""; /* end of header */
316 static const char *copy_line(const char *buf)
318 const char *eol = strchr(buf, '\n');
324 line = xmalloc(len + 1);
325 memcpy(line, buf, len);
330 static const char *copy_name(const char *buf)
332 const char *eol = strchr(buf, '\n');
333 const char *eoname = strstr(buf, " <");
336 if (!(eoname && eol && eoname < eol))
339 line = xmalloc(len + 1);
340 memcpy(line, buf, len);
345 static const char *copy_email(const char *buf)
347 const char *email = strchr(buf, '<');
348 const char *eoemail = strchr(email, '>');
351 if (!email || !eoemail)
354 len = eoemail - email;
355 line = xmalloc(len + 1);
356 memcpy(line, email, len);
361 static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
363 const char *eoemail = strstr(buf, "> ");
365 unsigned long timestamp;
367 enum date_mode date_mode = DATE_NORMAL;
371 * We got here because atomname ends in "date" or "date<something>";
372 * it's not possible that <something> is not ":<format>" because
373 * parse_atom() wouldn't have allowed it, so we can assume that no
374 * ":" means no format is specified, and use the default.
376 formatp = strchr(atomname, ':');
377 if (formatp != NULL) {
379 date_mode = parse_date_format(formatp);
384 timestamp = strtoul(eoemail + 2, &zone, 10);
385 if (timestamp == ULONG_MAX)
387 tz = strtol(zone, NULL, 10);
388 if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
390 v->s = xstrdup(show_date(timestamp, tz, date_mode));
398 /* See grab_values */
399 static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
402 int wholen = strlen(who);
403 const char *wholine = NULL;
405 for (i = 0; i < used_atom_cnt; i++) {
406 const char *name = used_atom[i];
407 struct atom_value *v = &val[i];
408 if (!!deref != (*name == '*'))
412 if (strncmp(who, name, wholen))
414 if (name[wholen] != 0 &&
415 strcmp(name + wholen, "name") &&
416 strcmp(name + wholen, "email") &&
417 prefixcmp(name + wholen, "date"))
420 wholine = find_wholine(who, wholen, buf, sz);
422 return; /* no point looking for it */
423 if (name[wholen] == 0)
424 v->s = copy_line(wholine);
425 else if (!strcmp(name + wholen, "name"))
426 v->s = copy_name(wholine);
427 else if (!strcmp(name + wholen, "email"))
428 v->s = copy_email(wholine);
429 else if (!prefixcmp(name + wholen, "date"))
430 grab_date(wholine, v, name);
433 /* For a tag or a commit object, if "creator" or "creatordate" is
434 * requested, do something special.
436 if (strcmp(who, "tagger") && strcmp(who, "committer"))
437 return; /* "author" for commit object is not wanted */
439 wholine = find_wholine(who, wholen, buf, sz);
442 for (i = 0; i < used_atom_cnt; i++) {
443 const char *name = used_atom[i];
444 struct atom_value *v = &val[i];
445 if (!!deref != (*name == '*'))
450 if (!prefixcmp(name, "creatordate"))
451 grab_date(wholine, v, name);
452 else if (!strcmp(name, "creator"))
453 v->s = copy_line(wholine);
457 static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
460 const char *eol = strchr(buf, '\n');
463 if (eol[1] == '\n') {
465 break; /* found end of header */
473 *sub = buf; /* first non-empty line */
474 buf = strchr(buf, '\n');
476 return; /* no body */
478 buf++; /* skip blank between subject and body */
482 /* See grab_values */
483 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
486 const char *subpos = NULL, *bodypos = NULL;
488 for (i = 0; i < used_atom_cnt; i++) {
489 const char *name = used_atom[i];
490 struct atom_value *v = &val[i];
491 if (!!deref != (*name == '*'))
495 if (strcmp(name, "subject") &&
496 strcmp(name, "body") &&
497 strcmp(name, "contents"))
500 find_subpos(buf, sz, &subpos, &bodypos);
504 if (!strcmp(name, "subject"))
505 v->s = copy_line(subpos);
506 else if (!strcmp(name, "body"))
507 v->s = xstrdup(bodypos);
508 else if (!strcmp(name, "contents"))
509 v->s = xstrdup(subpos);
513 /* We want to have empty print-string for field requests
514 * that do not apply (e.g. "authordate" for a tag object)
516 static void fill_missing_values(struct atom_value *val)
519 for (i = 0; i < used_atom_cnt; i++) {
520 struct atom_value *v = &val[i];
527 * val is a list of atom_value to hold returned values. Extract
528 * the values for atoms in used_atom array out of (obj, buf, sz).
529 * when deref is false, (obj, buf, sz) is the object that is
530 * pointed at by the ref itself; otherwise it is the object the
531 * ref (which is a tag) refers to.
533 static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
535 grab_common_values(val, deref, obj, buf, sz);
538 grab_tag_values(val, deref, obj, buf, sz);
539 grab_sub_body_contents(val, deref, obj, buf, sz);
540 grab_person("tagger", val, deref, obj, buf, sz);
543 grab_commit_values(val, deref, obj, buf, sz);
544 grab_sub_body_contents(val, deref, obj, buf, sz);
545 grab_person("author", val, deref, obj, buf, sz);
546 grab_person("committer", val, deref, obj, buf, sz);
549 // grab_tree_values(val, deref, obj, buf, sz);
552 // grab_blob_values(val, deref, obj, buf, sz);
555 die("Eh? Object of type %d?", obj->type);
560 * Parse the object referred by ref, and grab needed value.
562 static void populate_value(struct refinfo *ref)
568 const unsigned char *tagged;
570 ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
572 buf = get_obj(ref->objectname, &obj, &size, &eaten);
574 die("missing object %s for %s",
575 sha1_to_hex(ref->objectname), ref->refname);
577 die("parse_object_buffer failed on %s for %s",
578 sha1_to_hex(ref->objectname), ref->refname);
580 /* Fill in specials first */
581 for (i = 0; i < used_atom_cnt; i++) {
582 const char *name = used_atom[i];
583 struct atom_value *v = &ref->value[i];
584 if (!strcmp(name, "refname"))
586 else if (!strcmp(name, "*refname")) {
587 int len = strlen(ref->refname);
588 char *s = xmalloc(len + 4);
589 sprintf(s, "%s^{}", ref->refname);
594 grab_values(ref->value, 0, obj, buf, size);
598 /* If there is no atom that wants to know about tagged
599 * object, we are done.
601 if (!need_tagged || (obj->type != OBJ_TAG))
604 /* If it is a tag object, see if we use a value that derefs
605 * the object, and if we do grab the object it refers to.
607 tagged = ((struct tag *)obj)->tagged->sha1;
609 /* NEEDSWORK: This derefs tag only once, which
610 * is good to deal with chains of trust, but
611 * is not consistent with what deref_tag() does
612 * which peels the onion to the core.
614 buf = get_obj(tagged, &obj, &size, &eaten);
616 die("missing object %s for %s",
617 sha1_to_hex(tagged), ref->refname);
619 die("parse_object_buffer failed on %s for %s",
620 sha1_to_hex(tagged), ref->refname);
621 grab_values(ref->value, 1, obj, buf, size);
627 * Given a ref, return the value for the atom. This lazily gets value
628 * out of the object by calling populate value.
630 static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
634 fill_missing_values(ref->value);
636 *v = &ref->value[atom];
639 struct grab_ref_cbdata {
640 struct refinfo **grab_array;
641 const char **grab_pattern;
646 * A call-back given to for_each_ref(). It is unfortunate that we
647 * need to use global variables to pass extra information to this
650 static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
652 struct grab_ref_cbdata *cb = cb_data;
656 if (*cb->grab_pattern) {
657 const char **pattern;
658 int namelen = strlen(refname);
659 for (pattern = cb->grab_pattern; *pattern; pattern++) {
660 const char *p = *pattern;
661 int plen = strlen(p);
663 if ((plen <= namelen) &&
664 !strncmp(refname, p, plen) &&
665 (refname[plen] == '\0' ||
666 refname[plen] == '/'))
668 if (!fnmatch(p, refname, FNM_PATHNAME))
675 /* We do not open the object yet; sort may only need refname
676 * to do its job and the resulting list may yet to be pruned
679 ref = xcalloc(1, sizeof(*ref));
680 ref->refname = xstrdup(refname);
681 hashcpy(ref->objectname, sha1);
684 cb->grab_array = xrealloc(cb->grab_array,
685 sizeof(*cb->grab_array) * (cnt + 1));
686 cb->grab_array[cnt++] = ref;
691 static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
693 struct atom_value *va, *vb;
695 cmp_type cmp_type = used_atom_type[s->atom];
697 get_value(a, s->atom, &va);
698 get_value(b, s->atom, &vb);
701 cmp = strcmp(va->s, vb->s);
706 else if (va->ul == vb->ul)
712 return (s->reverse) ? -cmp : cmp;
715 static struct ref_sort *ref_sort;
716 static int compare_refs(const void *a_, const void *b_)
718 struct refinfo *a = *((struct refinfo **)a_);
719 struct refinfo *b = *((struct refinfo **)b_);
722 for (s = ref_sort; s; s = s->next) {
723 int cmp = cmp_ref_sort(s, a, b);
730 static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
733 qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
736 static void print_value(struct refinfo *ref, int atom, int quote_style)
738 struct atom_value *v;
739 get_value(ref, atom, &v);
740 switch (quote_style) {
745 sq_quote_print(stdout, v->s);
748 perl_quote_print(stdout, v->s);
751 python_quote_print(stdout, v->s);
754 tcl_quote_print(stdout, v->s);
759 static int hex1(char ch)
761 if ('0' <= ch && ch <= '9')
763 else if ('a' <= ch && ch <= 'f')
764 return ch - 'a' + 10;
765 else if ('A' <= ch && ch <= 'F')
766 return ch - 'A' + 10;
769 static int hex2(const char *cp)
772 return (hex1(cp[0]) << 4) | hex1(cp[1]);
777 static void emit(const char *cp, const char *ep)
779 while (*cp && (!ep || cp < ep)) {
784 int ch = hex2(cp + 1);
797 static void show_ref(struct refinfo *info, const char *format, int quote_style)
799 const char *cp, *sp, *ep;
801 for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
802 ep = strchr(sp, ')');
805 print_value(info, parse_atom(sp + 2, ep), quote_style);
808 sp = cp + strlen(cp);
814 static struct ref_sort *default_sort(void)
816 static const char cstr_name[] = "refname";
818 struct ref_sort *sort = xcalloc(1, sizeof(*sort));
821 sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
825 int cmd_for_each_ref(int ac, const char **av, const char *prefix)
828 const char *format = NULL;
829 struct ref_sort *sort = NULL, **sort_tail = &sort;
831 int quote_style = -1; /* unspecified yet */
832 struct refinfo **refs;
833 struct grab_ref_cbdata cbdata;
835 for (i = 1; i < ac; i++) {
836 const char *arg = av[i];
839 if (!strcmp(arg, "--")) {
843 if (!prefixcmp(arg, "--format=")) {
845 die("more than one --format?");
849 if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
850 if (0 <= quote_style)
851 die("more than one quoting style?");
852 quote_style = QUOTE_SHELL;
855 if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
856 if (0 <= quote_style)
857 die("more than one quoting style?");
858 quote_style = QUOTE_PERL;
861 if (!strcmp(arg, "--python") ) {
862 if (0 <= quote_style)
863 die("more than one quoting style?");
864 quote_style = QUOTE_PYTHON;
867 if (!strcmp(arg, "--tcl") ) {
868 if (0 <= quote_style)
869 die("more than one quoting style?");
870 quote_style = QUOTE_TCL;
873 if (!prefixcmp(arg, "--count=")) {
875 die("more than one --count?");
876 maxcount = atoi(arg + 8);
878 die("The number %s did not parse", arg);
881 if (!prefixcmp(arg, "--sort=")) {
882 struct ref_sort *s = xcalloc(1, sizeof(*s));
887 sort_tail = &s->next;
895 sort->atom = parse_atom(arg, arg+len);
901 quote_style = QUOTE_NONE;
904 sort = default_sort();
905 sort_atom_limit = used_atom_cnt;
907 format = "%(objectname) %(objecttype)\t%(refname)";
909 verify_format(format);
911 memset(&cbdata, 0, sizeof(cbdata));
912 cbdata.grab_pattern = av + i;
913 for_each_ref(grab_single_ref, &cbdata);
914 refs = cbdata.grab_array;
915 num_refs = cbdata.grab_cnt;
917 for (i = 0; i < used_atom_cnt; i++) {
918 if (used_atom[i][0] == '*') {
924 sort_refs(sort, refs, num_refs);
926 if (!maxcount || num_refs < maxcount)
928 for (i = 0; i < maxcount; i++)
929 show_ref(refs[i], format, quote_style);