Code

hooks-pre-commit: use \t, rather than a literal TAB in regexp
[git.git] / builtin-for-each-ref.c
1 #include "builtin.h"
2 #include "cache.h"
3 #include "refs.h"
4 #include "object.h"
5 #include "tag.h"
6 #include "commit.h"
7 #include "tree.h"
8 #include "blob.h"
9 #include "quote.h"
11 /* Quoting styles */
12 #define QUOTE_NONE 0
13 #define QUOTE_SHELL 1
14 #define QUOTE_PERL 2
15 #define QUOTE_PYTHON 3
16 #define QUOTE_TCL 4
18 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
20 struct atom_value {
21         const char *s;
22         unsigned long ul; /* used for sorting when not FIELD_STR */
23 };
25 struct ref_sort {
26         struct ref_sort *next;
27         int atom; /* index into used_atom array */
28         unsigned reverse : 1;
29 };
31 struct refinfo {
32         char *refname;
33         unsigned char objectname[20];
34         struct atom_value *value;
35 };
37 static struct {
38         const char *name;
39         cmp_type cmp_type;
40 } valid_atom[] = {
41         { "refname" },
42         { "objecttype" },
43         { "objectsize", FIELD_ULONG },
44         { "objectname" },
45         { "tree" },
46         { "parent" },
47         { "numparent", FIELD_ULONG },
48         { "object" },
49         { "type" },
50         { "tag" },
51         { "author" },
52         { "authorname" },
53         { "authoremail" },
54         { "authordate", FIELD_TIME },
55         { "committer" },
56         { "committername" },
57         { "committeremail" },
58         { "committerdate", FIELD_TIME },
59         { "tagger" },
60         { "taggername" },
61         { "taggeremail" },
62         { "taggerdate", FIELD_TIME },
63         { "creator" },
64         { "creatordate", FIELD_TIME },
65         { "subject" },
66         { "body" },
67         { "contents" },
68 };
70 /*
71  * An atom is a valid field atom listed above, possibly prefixed with
72  * a "*" to denote deref_tag().
73  *
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
78  * array.
79  */
80 static const char **used_atom;
81 static cmp_type *used_atom_type;
82 static int used_atom_cnt, sort_atom_limit, need_tagged;
84 /*
85  * Used to parse format string and sort specifiers
86  */
87 static int parse_atom(const char *atom, const char *ep)
88 {
89         const char *sp;
90         int i, at;
92         sp = atom;
93         if (*sp == '*' && sp < ep)
94                 sp++; /* deref */
95         if (ep <= sp)
96                 die("malformed field name: %.*s", (int)(ep-atom), atom);
98         /* Do we have the atom already used elsewhere? */
99         for (i = 0; i < used_atom_cnt; i++) {
100                 int len = strlen(used_atom[i]);
101                 if (len == ep - atom && !memcmp(used_atom[i], atom, len))
102                         return i;
103         }
105         /* Is the atom a valid one? */
106         for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
107                 int len = strlen(valid_atom[i].name);
108                 /*
109                  * If the atom name has a colon, strip it and everything after
110                  * it off - it specifies the format for this entry, and
111                  * shouldn't be used for checking against the valid_atom
112                  * table.
113                  */
114                 const char *formatp = strchr(sp, ':');
115                 if (!formatp || ep < formatp)
116                         formatp = ep;
117                 if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
118                         break;
119         }
121         if (ARRAY_SIZE(valid_atom) <= i)
122                 die("unknown field name: %.*s", (int)(ep-atom), atom);
124         /* Add it in, including the deref prefix */
125         at = used_atom_cnt;
126         used_atom_cnt++;
127         used_atom = xrealloc(used_atom,
128                              (sizeof *used_atom) * used_atom_cnt);
129         used_atom_type = xrealloc(used_atom_type,
130                                   (sizeof(*used_atom_type) * used_atom_cnt));
131         used_atom[at] = xmemdupz(atom, ep - atom);
132         used_atom_type[at] = valid_atom[i].cmp_type;
133         return at;
136 /*
137  * In a format string, find the next occurrence of %(atom).
138  */
139 static const char *find_next(const char *cp)
141         while (*cp) {
142                 if (*cp == '%') {
143                         /* %( is the start of an atom;
144                          * %% is a quoted per-cent.
145                          */
146                         if (cp[1] == '(')
147                                 return cp;
148                         else if (cp[1] == '%')
149                                 cp++; /* skip over two % */
150                         /* otherwise this is a singleton, literal % */
151                 }
152                 cp++;
153         }
154         return NULL;
157 /*
158  * Make sure the format string is well formed, and parse out
159  * the used atoms.
160  */
161 static void verify_format(const char *format)
163         const char *cp, *sp;
164         for (cp = format; *cp && (sp = find_next(cp)); ) {
165                 const char *ep = strchr(sp, ')');
166                 if (!ep)
167                         die("malformatted format string %s", sp);
168                 /* sp points at "%(" and ep points at the closing ")" */
169                 parse_atom(sp + 2, ep);
170                 cp = ep + 1;
171         }
174 /*
175  * Given an object name, read the object data and size, and return a
176  * "struct object".  If the object data we are returning is also borrowed
177  * by the "struct object" representation, set *eaten as well---it is a
178  * signal from parse_object_buffer to us not to free the buffer.
179  */
180 static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
182         enum object_type type;
183         void *buf = read_sha1_file(sha1, &type, sz);
185         if (buf)
186                 *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
187         else
188                 *obj = NULL;
189         return buf;
192 /* See grab_values */
193 static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
195         int i;
197         for (i = 0; i < used_atom_cnt; i++) {
198                 const char *name = used_atom[i];
199                 struct atom_value *v = &val[i];
200                 if (!!deref != (*name == '*'))
201                         continue;
202                 if (deref)
203                         name++;
204                 if (!strcmp(name, "objecttype"))
205                         v->s = typename(obj->type);
206                 else if (!strcmp(name, "objectsize")) {
207                         char *s = xmalloc(40);
208                         sprintf(s, "%lu", sz);
209                         v->ul = sz;
210                         v->s = s;
211                 }
212                 else if (!strcmp(name, "objectname")) {
213                         char *s = xmalloc(41);
214                         strcpy(s, sha1_to_hex(obj->sha1));
215                         v->s = s;
216                 }
217         }
220 /* See grab_values */
221 static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
223         int i;
224         struct tag *tag = (struct tag *) obj;
226         for (i = 0; i < used_atom_cnt; i++) {
227                 const char *name = used_atom[i];
228                 struct atom_value *v = &val[i];
229                 if (!!deref != (*name == '*'))
230                         continue;
231                 if (deref)
232                         name++;
233                 if (!strcmp(name, "tag"))
234                         v->s = tag->tag;
235         }
238 static int num_parents(struct commit *commit)
240         struct commit_list *parents;
241         int i;
243         for (i = 0, parents = commit->parents;
244              parents;
245              parents = parents->next)
246                 i++;
247         return i;
250 /* See grab_values */
251 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
253         int i;
254         struct commit *commit = (struct commit *) obj;
256         for (i = 0; i < used_atom_cnt; i++) {
257                 const char *name = used_atom[i];
258                 struct atom_value *v = &val[i];
259                 if (!!deref != (*name == '*'))
260                         continue;
261                 if (deref)
262                         name++;
263                 if (!strcmp(name, "tree")) {
264                         char *s = xmalloc(41);
265                         strcpy(s, sha1_to_hex(commit->tree->object.sha1));
266                         v->s = s;
267                 }
268                 if (!strcmp(name, "numparent")) {
269                         char *s = xmalloc(40);
270                         v->ul = num_parents(commit);
271                         sprintf(s, "%lu", v->ul);
272                         v->s = s;
273                 }
274                 else if (!strcmp(name, "parent")) {
275                         int num = num_parents(commit);
276                         int i;
277                         struct commit_list *parents;
278                         char *s = xmalloc(41 * num + 1);
279                         v->s = s;
280                         for (i = 0, parents = commit->parents;
281                              parents;
282                              parents = parents->next, i = i + 41) {
283                                 struct commit *parent = parents->item;
284                                 strcpy(s+i, sha1_to_hex(parent->object.sha1));
285                                 if (parents->next)
286                                         s[i+40] = ' ';
287                         }
288                         if (!i)
289                                 *s = '\0';
290                 }
291         }
294 static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
296         const char *eol;
297         while (*buf) {
298                 if (!strncmp(buf, who, wholen) &&
299                     buf[wholen] == ' ')
300                         return buf + wholen + 1;
301                 eol = strchr(buf, '\n');
302                 if (!eol)
303                         return "";
304                 eol++;
305                 if (eol[1] == '\n')
306                         return ""; /* end of header */
307                 buf = eol;
308         }
309         return "";
312 static const char *copy_line(const char *buf)
314         const char *eol = strchr(buf, '\n');
315         if (!eol)
316                 return "";
317         return xmemdupz(buf, eol - buf);
320 static const char *copy_name(const char *buf)
322         const char *cp;
323         for (cp = buf; *cp && *cp != '\n'; cp++) {
324                 if (!strncmp(cp, " <", 2))
325                         return xmemdupz(buf, cp - buf);
326         }
327         return "";
330 static const char *copy_email(const char *buf)
332         const char *email = strchr(buf, '<');
333         const char *eoemail = strchr(email, '>');
334         if (!email || !eoemail)
335                 return "";
336         return xmemdupz(email, eoemail + 1 - email);
339 static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
341         const char *eoemail = strstr(buf, "> ");
342         char *zone;
343         unsigned long timestamp;
344         long tz;
345         enum date_mode date_mode = DATE_NORMAL;
346         const char *formatp;
348         /*
349          * We got here because atomname ends in "date" or "date<something>";
350          * it's not possible that <something> is not ":<format>" because
351          * parse_atom() wouldn't have allowed it, so we can assume that no
352          * ":" means no format is specified, and use the default.
353          */
354         formatp = strchr(atomname, ':');
355         if (formatp != NULL) {
356                 formatp++;
357                 date_mode = parse_date_format(formatp);
358         }
360         if (!eoemail)
361                 goto bad;
362         timestamp = strtoul(eoemail + 2, &zone, 10);
363         if (timestamp == ULONG_MAX)
364                 goto bad;
365         tz = strtol(zone, NULL, 10);
366         if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
367                 goto bad;
368         v->s = xstrdup(show_date(timestamp, tz, date_mode));
369         v->ul = timestamp;
370         return;
371  bad:
372         v->s = "";
373         v->ul = 0;
376 /* See grab_values */
377 static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
379         int i;
380         int wholen = strlen(who);
381         const char *wholine = NULL;
383         for (i = 0; i < used_atom_cnt; i++) {
384                 const char *name = used_atom[i];
385                 struct atom_value *v = &val[i];
386                 if (!!deref != (*name == '*'))
387                         continue;
388                 if (deref)
389                         name++;
390                 if (strncmp(who, name, wholen))
391                         continue;
392                 if (name[wholen] != 0 &&
393                     strcmp(name + wholen, "name") &&
394                     strcmp(name + wholen, "email") &&
395                     prefixcmp(name + wholen, "date"))
396                         continue;
397                 if (!wholine)
398                         wholine = find_wholine(who, wholen, buf, sz);
399                 if (!wholine)
400                         return; /* no point looking for it */
401                 if (name[wholen] == 0)
402                         v->s = copy_line(wholine);
403                 else if (!strcmp(name + wholen, "name"))
404                         v->s = copy_name(wholine);
405                 else if (!strcmp(name + wholen, "email"))
406                         v->s = copy_email(wholine);
407                 else if (!prefixcmp(name + wholen, "date"))
408                         grab_date(wholine, v, name);
409         }
411         /* For a tag or a commit object, if "creator" or "creatordate" is
412          * requested, do something special.
413          */
414         if (strcmp(who, "tagger") && strcmp(who, "committer"))
415                 return; /* "author" for commit object is not wanted */
416         if (!wholine)
417                 wholine = find_wholine(who, wholen, buf, sz);
418         if (!wholine)
419                 return;
420         for (i = 0; i < used_atom_cnt; i++) {
421                 const char *name = used_atom[i];
422                 struct atom_value *v = &val[i];
423                 if (!!deref != (*name == '*'))
424                         continue;
425                 if (deref)
426                         name++;
428                 if (!prefixcmp(name, "creatordate"))
429                         grab_date(wholine, v, name);
430                 else if (!strcmp(name, "creator"))
431                         v->s = copy_line(wholine);
432         }
435 static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
437         while (*buf) {
438                 const char *eol = strchr(buf, '\n');
439                 if (!eol)
440                         return;
441                 if (eol[1] == '\n') {
442                         buf = eol + 1;
443                         break; /* found end of header */
444                 }
445                 buf = eol + 1;
446         }
447         while (*buf == '\n')
448                 buf++;
449         if (!*buf)
450                 return;
451         *sub = buf; /* first non-empty line */
452         buf = strchr(buf, '\n');
453         if (!buf)
454                 return; /* no body */
455         while (*buf == '\n')
456                 buf++; /* skip blank between subject and body */
457         *body = buf;
460 /* See grab_values */
461 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
463         int i;
464         const char *subpos = NULL, *bodypos = NULL;
466         for (i = 0; i < used_atom_cnt; i++) {
467                 const char *name = used_atom[i];
468                 struct atom_value *v = &val[i];
469                 if (!!deref != (*name == '*'))
470                         continue;
471                 if (deref)
472                         name++;
473                 if (strcmp(name, "subject") &&
474                     strcmp(name, "body") &&
475                     strcmp(name, "contents"))
476                         continue;
477                 if (!subpos)
478                         find_subpos(buf, sz, &subpos, &bodypos);
479                 if (!subpos)
480                         return;
482                 if (!strcmp(name, "subject"))
483                         v->s = copy_line(subpos);
484                 else if (!strcmp(name, "body"))
485                         v->s = xstrdup(bodypos);
486                 else if (!strcmp(name, "contents"))
487                         v->s = xstrdup(subpos);
488         }
491 /* We want to have empty print-string for field requests
492  * that do not apply (e.g. "authordate" for a tag object)
493  */
494 static void fill_missing_values(struct atom_value *val)
496         int i;
497         for (i = 0; i < used_atom_cnt; i++) {
498                 struct atom_value *v = &val[i];
499                 if (v->s == NULL)
500                         v->s = "";
501         }
504 /*
505  * val is a list of atom_value to hold returned values.  Extract
506  * the values for atoms in used_atom array out of (obj, buf, sz).
507  * when deref is false, (obj, buf, sz) is the object that is
508  * pointed at by the ref itself; otherwise it is the object the
509  * ref (which is a tag) refers to.
510  */
511 static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
513         grab_common_values(val, deref, obj, buf, sz);
514         switch (obj->type) {
515         case OBJ_TAG:
516                 grab_tag_values(val, deref, obj, buf, sz);
517                 grab_sub_body_contents(val, deref, obj, buf, sz);
518                 grab_person("tagger", val, deref, obj, buf, sz);
519                 break;
520         case OBJ_COMMIT:
521                 grab_commit_values(val, deref, obj, buf, sz);
522                 grab_sub_body_contents(val, deref, obj, buf, sz);
523                 grab_person("author", val, deref, obj, buf, sz);
524                 grab_person("committer", val, deref, obj, buf, sz);
525                 break;
526         case OBJ_TREE:
527                 // grab_tree_values(val, deref, obj, buf, sz);
528                 break;
529         case OBJ_BLOB:
530                 // grab_blob_values(val, deref, obj, buf, sz);
531                 break;
532         default:
533                 die("Eh?  Object of type %d?", obj->type);
534         }
537 /*
538  * Parse the object referred by ref, and grab needed value.
539  */
540 static void populate_value(struct refinfo *ref)
542         void *buf;
543         struct object *obj;
544         int eaten, i;
545         unsigned long size;
546         const unsigned char *tagged;
548         ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
550         buf = get_obj(ref->objectname, &obj, &size, &eaten);
551         if (!buf)
552                 die("missing object %s for %s",
553                     sha1_to_hex(ref->objectname), ref->refname);
554         if (!obj)
555                 die("parse_object_buffer failed on %s for %s",
556                     sha1_to_hex(ref->objectname), ref->refname);
558         /* Fill in specials first */
559         for (i = 0; i < used_atom_cnt; i++) {
560                 const char *name = used_atom[i];
561                 struct atom_value *v = &ref->value[i];
562                 if (!strcmp(name, "refname"))
563                         v->s = ref->refname;
564                 else if (!strcmp(name, "*refname")) {
565                         int len = strlen(ref->refname);
566                         char *s = xmalloc(len + 4);
567                         sprintf(s, "%s^{}", ref->refname);
568                         v->s = s;
569                 }
570         }
572         grab_values(ref->value, 0, obj, buf, size);
573         if (!eaten)
574                 free(buf);
576         /* If there is no atom that wants to know about tagged
577          * object, we are done.
578          */
579         if (!need_tagged || (obj->type != OBJ_TAG))
580                 return;
582         /* If it is a tag object, see if we use a value that derefs
583          * the object, and if we do grab the object it refers to.
584          */
585         tagged = ((struct tag *)obj)->tagged->sha1;
587         /* NEEDSWORK: This derefs tag only once, which
588          * is good to deal with chains of trust, but
589          * is not consistent with what deref_tag() does
590          * which peels the onion to the core.
591          */
592         buf = get_obj(tagged, &obj, &size, &eaten);
593         if (!buf)
594                 die("missing object %s for %s",
595                     sha1_to_hex(tagged), ref->refname);
596         if (!obj)
597                 die("parse_object_buffer failed on %s for %s",
598                     sha1_to_hex(tagged), ref->refname);
599         grab_values(ref->value, 1, obj, buf, size);
600         if (!eaten)
601                 free(buf);
604 /*
605  * Given a ref, return the value for the atom.  This lazily gets value
606  * out of the object by calling populate value.
607  */
608 static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
610         if (!ref->value) {
611                 populate_value(ref);
612                 fill_missing_values(ref->value);
613         }
614         *v = &ref->value[atom];
617 struct grab_ref_cbdata {
618         struct refinfo **grab_array;
619         const char **grab_pattern;
620         int grab_cnt;
621 };
623 /*
624  * A call-back given to for_each_ref().  It is unfortunate that we
625  * need to use global variables to pass extra information to this
626  * function.
627  */
628 static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
630         struct grab_ref_cbdata *cb = cb_data;
631         struct refinfo *ref;
632         int cnt;
634         if (*cb->grab_pattern) {
635                 const char **pattern;
636                 int namelen = strlen(refname);
637                 for (pattern = cb->grab_pattern; *pattern; pattern++) {
638                         const char *p = *pattern;
639                         int plen = strlen(p);
641                         if ((plen <= namelen) &&
642                             !strncmp(refname, p, plen) &&
643                             (refname[plen] == '\0' ||
644                              refname[plen] == '/'))
645                                 break;
646                         if (!fnmatch(p, refname, FNM_PATHNAME))
647                                 break;
648                 }
649                 if (!*pattern)
650                         return 0;
651         }
653         /* We do not open the object yet; sort may only need refname
654          * to do its job and the resulting list may yet to be pruned
655          * by maxcount logic.
656          */
657         ref = xcalloc(1, sizeof(*ref));
658         ref->refname = xstrdup(refname);
659         hashcpy(ref->objectname, sha1);
661         cnt = cb->grab_cnt;
662         cb->grab_array = xrealloc(cb->grab_array,
663                                   sizeof(*cb->grab_array) * (cnt + 1));
664         cb->grab_array[cnt++] = ref;
665         cb->grab_cnt = cnt;
666         return 0;
669 static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
671         struct atom_value *va, *vb;
672         int cmp;
673         cmp_type cmp_type = used_atom_type[s->atom];
675         get_value(a, s->atom, &va);
676         get_value(b, s->atom, &vb);
677         switch (cmp_type) {
678         case FIELD_STR:
679                 cmp = strcmp(va->s, vb->s);
680                 break;
681         default:
682                 if (va->ul < vb->ul)
683                         cmp = -1;
684                 else if (va->ul == vb->ul)
685                         cmp = 0;
686                 else
687                         cmp = 1;
688                 break;
689         }
690         return (s->reverse) ? -cmp : cmp;
693 static struct ref_sort *ref_sort;
694 static int compare_refs(const void *a_, const void *b_)
696         struct refinfo *a = *((struct refinfo **)a_);
697         struct refinfo *b = *((struct refinfo **)b_);
698         struct ref_sort *s;
700         for (s = ref_sort; s; s = s->next) {
701                 int cmp = cmp_ref_sort(s, a, b);
702                 if (cmp)
703                         return cmp;
704         }
705         return 0;
708 static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
710         ref_sort = sort;
711         qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
714 static void print_value(struct refinfo *ref, int atom, int quote_style)
716         struct atom_value *v;
717         get_value(ref, atom, &v);
718         switch (quote_style) {
719         case QUOTE_NONE:
720                 fputs(v->s, stdout);
721                 break;
722         case QUOTE_SHELL:
723                 sq_quote_print(stdout, v->s);
724                 break;
725         case QUOTE_PERL:
726                 perl_quote_print(stdout, v->s);
727                 break;
728         case QUOTE_PYTHON:
729                 python_quote_print(stdout, v->s);
730                 break;
731         case QUOTE_TCL:
732                 tcl_quote_print(stdout, v->s);
733                 break;
734         }
737 static int hex1(char ch)
739         if ('0' <= ch && ch <= '9')
740                 return ch - '0';
741         else if ('a' <= ch && ch <= 'f')
742                 return ch - 'a' + 10;
743         else if ('A' <= ch && ch <= 'F')
744                 return ch - 'A' + 10;
745         return -1;
747 static int hex2(const char *cp)
749         if (cp[0] && cp[1])
750                 return (hex1(cp[0]) << 4) | hex1(cp[1]);
751         else
752                 return -1;
755 static void emit(const char *cp, const char *ep)
757         while (*cp && (!ep || cp < ep)) {
758                 if (*cp == '%') {
759                         if (cp[1] == '%')
760                                 cp++;
761                         else {
762                                 int ch = hex2(cp + 1);
763                                 if (0 <= ch) {
764                                         putchar(ch);
765                                         cp += 3;
766                                         continue;
767                                 }
768                         }
769                 }
770                 putchar(*cp);
771                 cp++;
772         }
775 static void show_ref(struct refinfo *info, const char *format, int quote_style)
777         const char *cp, *sp, *ep;
779         for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
780                 ep = strchr(sp, ')');
781                 if (cp < sp)
782                         emit(cp, sp);
783                 print_value(info, parse_atom(sp + 2, ep), quote_style);
784         }
785         if (*cp) {
786                 sp = cp + strlen(cp);
787                 emit(cp, sp);
788         }
789         putchar('\n');
792 static struct ref_sort *default_sort(void)
794         static const char cstr_name[] = "refname";
796         struct ref_sort *sort = xcalloc(1, sizeof(*sort));
798         sort->next = NULL;
799         sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
800         return sort;
803 int cmd_for_each_ref(int ac, const char **av, const char *prefix)
805         int i, num_refs;
806         const char *format = NULL;
807         struct ref_sort *sort = NULL, **sort_tail = &sort;
808         int maxcount = 0;
809         int quote_style = -1; /* unspecified yet */
810         struct refinfo **refs;
811         struct grab_ref_cbdata cbdata;
813         for (i = 1; i < ac; i++) {
814                 const char *arg = av[i];
815                 if (arg[0] != '-')
816                         break;
817                 if (!strcmp(arg, "--")) {
818                         i++;
819                         break;
820                 }
821                 if (!prefixcmp(arg, "--format=")) {
822                         if (format)
823                                 die("more than one --format?");
824                         format = arg + 9;
825                         continue;
826                 }
827                 if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
828                         if (0 <= quote_style)
829                                 die("more than one quoting style?");
830                         quote_style = QUOTE_SHELL;
831                         continue;
832                 }
833                 if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
834                         if (0 <= quote_style)
835                                 die("more than one quoting style?");
836                         quote_style = QUOTE_PERL;
837                         continue;
838                 }
839                 if (!strcmp(arg, "--python") ) {
840                         if (0 <= quote_style)
841                                 die("more than one quoting style?");
842                         quote_style = QUOTE_PYTHON;
843                         continue;
844                 }
845                 if (!strcmp(arg, "--tcl") ) {
846                         if (0 <= quote_style)
847                                 die("more than one quoting style?");
848                         quote_style = QUOTE_TCL;
849                         continue;
850                 }
851                 if (!prefixcmp(arg, "--count=")) {
852                         if (maxcount)
853                                 die("more than one --count?");
854                         maxcount = atoi(arg + 8);
855                         if (maxcount <= 0)
856                                 die("The number %s did not parse", arg);
857                         continue;
858                 }
859                 if (!prefixcmp(arg, "--sort=")) {
860                         struct ref_sort *s = xcalloc(1, sizeof(*s));
861                         int len;
863                         s->next = NULL;
864                         *sort_tail = s;
865                         sort_tail = &s->next;
867                         arg += 7;
868                         if (*arg == '-') {
869                                 s->reverse = 1;
870                                 arg++;
871                         }
872                         len = strlen(arg);
873                         sort->atom = parse_atom(arg, arg+len);
874                         continue;
875                 }
876                 break;
877         }
878         if (quote_style < 0)
879                 quote_style = QUOTE_NONE;
881         if (!sort)
882                 sort = default_sort();
883         sort_atom_limit = used_atom_cnt;
884         if (!format)
885                 format = "%(objectname) %(objecttype)\t%(refname)";
887         verify_format(format);
889         memset(&cbdata, 0, sizeof(cbdata));
890         cbdata.grab_pattern = av + i;
891         for_each_ref(grab_single_ref, &cbdata);
892         refs = cbdata.grab_array;
893         num_refs = cbdata.grab_cnt;
895         for (i = 0; i < used_atom_cnt; i++) {
896                 if (used_atom[i][0] == '*') {
897                         need_tagged = 1;
898                         break;
899                 }
900         }
902         sort_refs(sort, refs, num_refs);
904         if (!maxcount || num_refs < maxcount)
905                 maxcount = num_refs;
906         for (i = 0; i < maxcount; i++)
907                 show_ref(refs[i], format, quote_style);
908         return 0;