Code

Make merge-recursive honor diff.renamelimit
[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         char *n;
91         int i, at;
93         sp = atom;
94         if (*sp == '*' && sp < ep)
95                 sp++; /* deref */
96         if (ep <= sp)
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))
103                         return i;
104         }
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);
109                 if (len == ep - sp && !memcmp(valid_atom[i].name, sp, len))
110                         break;
111         }
113         if (ARRAY_SIZE(valid_atom) <= i)
114                 die("unknown field name: %.*s", (int)(ep-atom), atom);
116         /* Add it in, including the deref prefix */
117         at = used_atom_cnt;
118         used_atom_cnt++;
119         used_atom = xrealloc(used_atom,
120                              (sizeof *used_atom) * used_atom_cnt);
121         used_atom_type = xrealloc(used_atom_type,
122                                   (sizeof(*used_atom_type) * used_atom_cnt));
123         n = xmalloc(ep - atom + 1);
124         memcpy(n, atom, ep - atom);
125         n[ep-atom] = 0;
126         used_atom[at] = n;
127         used_atom_type[at] = valid_atom[i].cmp_type;
128         return at;
131 /*
132  * In a format string, find the next occurrence of %(atom).
133  */
134 static const char *find_next(const char *cp)
136         while (*cp) {
137                 if (*cp == '%') {
138                         /* %( is the start of an atom;
139                          * %% is a quoted per-cent.
140                          */
141                         if (cp[1] == '(')
142                                 return cp;
143                         else if (cp[1] == '%')
144                                 cp++; /* skip over two % */
145                         /* otherwise this is a singleton, literal % */
146                 }
147                 cp++;
148         }
149         return NULL;
152 /*
153  * Make sure the format string is well formed, and parse out
154  * the used atoms.
155  */
156 static void verify_format(const char *format)
158         const char *cp, *sp;
159         for (cp = format; *cp && (sp = find_next(cp)); ) {
160                 const char *ep = strchr(sp, ')');
161                 if (!ep)
162                         die("malformatted format string %s", sp);
163                 /* sp points at "%(" and ep points at the closing ")" */
164                 parse_atom(sp + 2, ep);
165                 cp = ep + 1;
166         }
169 /*
170  * Given an object name, read the object data and size, and return a
171  * "struct object".  If the object data we are returning is also borrowed
172  * by the "struct object" representation, set *eaten as well---it is a
173  * signal from parse_object_buffer to us not to free the buffer.
174  */
175 static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
177         enum object_type type;
178         void *buf = read_sha1_file(sha1, &type, sz);
180         if (buf)
181                 *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
182         else
183                 *obj = NULL;
184         return buf;
187 /* See grab_values */
188 static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
190         int i;
192         for (i = 0; i < used_atom_cnt; i++) {
193                 const char *name = used_atom[i];
194                 struct atom_value *v = &val[i];
195                 if (!!deref != (*name == '*'))
196                         continue;
197                 if (deref)
198                         name++;
199                 if (!strcmp(name, "objecttype"))
200                         v->s = typename(obj->type);
201                 else if (!strcmp(name, "objectsize")) {
202                         char *s = xmalloc(40);
203                         sprintf(s, "%lu", sz);
204                         v->ul = sz;
205                         v->s = s;
206                 }
207                 else if (!strcmp(name, "objectname")) {
208                         char *s = xmalloc(41);
209                         strcpy(s, sha1_to_hex(obj->sha1));
210                         v->s = s;
211                 }
212         }
215 /* See grab_values */
216 static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
218         int i;
219         struct tag *tag = (struct tag *) obj;
221         for (i = 0; i < used_atom_cnt; i++) {
222                 const char *name = used_atom[i];
223                 struct atom_value *v = &val[i];
224                 if (!!deref != (*name == '*'))
225                         continue;
226                 if (deref)
227                         name++;
228                 if (!strcmp(name, "tag"))
229                         v->s = tag->tag;
230         }
233 static int num_parents(struct commit *commit)
235         struct commit_list *parents;
236         int i;
238         for (i = 0, parents = commit->parents;
239              parents;
240              parents = parents->next)
241                 i++;
242         return i;
245 /* See grab_values */
246 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
248         int i;
249         struct commit *commit = (struct commit *) obj;
251         for (i = 0; i < used_atom_cnt; i++) {
252                 const char *name = used_atom[i];
253                 struct atom_value *v = &val[i];
254                 if (!!deref != (*name == '*'))
255                         continue;
256                 if (deref)
257                         name++;
258                 if (!strcmp(name, "tree")) {
259                         char *s = xmalloc(41);
260                         strcpy(s, sha1_to_hex(commit->tree->object.sha1));
261                         v->s = s;
262                 }
263                 if (!strcmp(name, "numparent")) {
264                         char *s = xmalloc(40);
265                         v->ul = num_parents(commit);
266                         sprintf(s, "%lu", v->ul);
267                         v->s = s;
268                 }
269                 else if (!strcmp(name, "parent")) {
270                         int num = num_parents(commit);
271                         int i;
272                         struct commit_list *parents;
273                         char *s = xmalloc(41 * num + 1);
274                         v->s = s;
275                         for (i = 0, parents = commit->parents;
276                              parents;
277                              parents = parents->next, i = i + 41) {
278                                 struct commit *parent = parents->item;
279                                 strcpy(s+i, sha1_to_hex(parent->object.sha1));
280                                 if (parents->next)
281                                         s[i+40] = ' ';
282                         }
283                         if (!i)
284                                 *s = '\0';
285                 }
286         }
289 static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
291         const char *eol;
292         while (*buf) {
293                 if (!strncmp(buf, who, wholen) &&
294                     buf[wholen] == ' ')
295                         return buf + wholen + 1;
296                 eol = strchr(buf, '\n');
297                 if (!eol)
298                         return "";
299                 eol++;
300                 if (eol[1] == '\n')
301                         return ""; /* end of header */
302                 buf = eol;
303         }
304         return "";
307 static const char *copy_line(const char *buf)
309         const char *eol = strchr(buf, '\n');
310         char *line;
311         int len;
312         if (!eol)
313                 return "";
314         len = eol - buf;
315         line = xmalloc(len + 1);
316         memcpy(line, buf, len);
317         line[len] = 0;
318         return line;
321 static const char *copy_name(const char *buf)
323         const char *eol = strchr(buf, '\n');
324         const char *eoname = strstr(buf, " <");
325         char *line;
326         int len;
327         if (!(eoname && eol && eoname < eol))
328                 return "";
329         len = eoname - buf;
330         line = xmalloc(len + 1);
331         memcpy(line, buf, len);
332         line[len] = 0;
333         return line;
336 static const char *copy_email(const char *buf)
338         const char *email = strchr(buf, '<');
339         const char *eoemail = strchr(email, '>');
340         char *line;
341         int len;
342         if (!email || !eoemail)
343                 return "";
344         eoemail++;
345         len = eoemail - email;
346         line = xmalloc(len + 1);
347         memcpy(line, email, len);
348         line[len] = 0;
349         return line;
352 static void grab_date(const char *buf, struct atom_value *v)
354         const char *eoemail = strstr(buf, "> ");
355         char *zone;
356         unsigned long timestamp;
357         long tz;
359         if (!eoemail)
360                 goto bad;
361         timestamp = strtoul(eoemail + 2, &zone, 10);
362         if (timestamp == ULONG_MAX)
363                 goto bad;
364         tz = strtol(zone, NULL, 10);
365         if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
366                 goto bad;
367         v->s = xstrdup(show_date(timestamp, tz, 0));
368         v->ul = timestamp;
369         return;
370  bad:
371         v->s = "";
372         v->ul = 0;
375 /* See grab_values */
376 static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
378         int i;
379         int wholen = strlen(who);
380         const char *wholine = NULL;
382         for (i = 0; i < used_atom_cnt; i++) {
383                 const char *name = used_atom[i];
384                 struct atom_value *v = &val[i];
385                 if (!!deref != (*name == '*'))
386                         continue;
387                 if (deref)
388                         name++;
389                 if (strncmp(who, name, wholen))
390                         continue;
391                 if (name[wholen] != 0 &&
392                     strcmp(name + wholen, "name") &&
393                     strcmp(name + wholen, "email") &&
394                     strcmp(name + wholen, "date"))
395                         continue;
396                 if (!wholine)
397                         wholine = find_wholine(who, wholen, buf, sz);
398                 if (!wholine)
399                         return; /* no point looking for it */
400                 if (name[wholen] == 0)
401                         v->s = copy_line(wholine);
402                 else if (!strcmp(name + wholen, "name"))
403                         v->s = copy_name(wholine);
404                 else if (!strcmp(name + wholen, "email"))
405                         v->s = copy_email(wholine);
406                 else if (!strcmp(name + wholen, "date"))
407                         grab_date(wholine, v);
408         }
410         /* For a tag or a commit object, if "creator" or "creatordate" is
411          * requested, do something special.
412          */
413         if (strcmp(who, "tagger") && strcmp(who, "committer"))
414                 return; /* "author" for commit object is not wanted */
415         if (!wholine)
416                 wholine = find_wholine(who, wholen, buf, sz);
417         if (!wholine)
418                 return;
419         for (i = 0; i < used_atom_cnt; i++) {
420                 const char *name = used_atom[i];
421                 struct atom_value *v = &val[i];
422                 if (!!deref != (*name == '*'))
423                         continue;
424                 if (deref)
425                         name++;
427                 if (!strcmp(name, "creatordate"))
428                         grab_date(wholine, v);
429                 else if (!strcmp(name, "creator"))
430                         v->s = copy_line(wholine);
431         }
434 static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
436         while (*buf) {
437                 const char *eol = strchr(buf, '\n');
438                 if (!eol)
439                         return;
440                 if (eol[1] == '\n') {
441                         buf = eol + 1;
442                         break; /* found end of header */
443                 }
444                 buf = eol + 1;
445         }
446         while (*buf == '\n')
447                 buf++;
448         if (!*buf)
449                 return;
450         *sub = buf; /* first non-empty line */
451         buf = strchr(buf, '\n');
452         if (!buf)
453                 return; /* no body */
454         while (*buf == '\n')
455                 buf++; /* skip blank between subject and body */
456         *body = buf;
459 /* See grab_values */
460 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
462         int i;
463         const char *subpos = NULL, *bodypos = NULL;
465         for (i = 0; i < used_atom_cnt; i++) {
466                 const char *name = used_atom[i];
467                 struct atom_value *v = &val[i];
468                 if (!!deref != (*name == '*'))
469                         continue;
470                 if (deref)
471                         name++;
472                 if (strcmp(name, "subject") &&
473                     strcmp(name, "body") &&
474                     strcmp(name, "contents"))
475                         continue;
476                 if (!subpos)
477                         find_subpos(buf, sz, &subpos, &bodypos);
478                 if (!subpos)
479                         return;
481                 if (!strcmp(name, "subject"))
482                         v->s = copy_line(subpos);
483                 else if (!strcmp(name, "body"))
484                         v->s = xstrdup(bodypos);
485                 else if (!strcmp(name, "contents"))
486                         v->s = xstrdup(subpos);
487         }
490 /* We want to have empty print-string for field requests
491  * that do not apply (e.g. "authordate" for a tag object)
492  */
493 static void fill_missing_values(struct atom_value *val)
495         int i;
496         for (i = 0; i < used_atom_cnt; i++) {
497                 struct atom_value *v = &val[i];
498                 if (v->s == NULL)
499                         v->s = "";
500         }
503 /*
504  * val is a list of atom_value to hold returned values.  Extract
505  * the values for atoms in used_atom array out of (obj, buf, sz).
506  * when deref is false, (obj, buf, sz) is the object that is
507  * pointed at by the ref itself; otherwise it is the object the
508  * ref (which is a tag) refers to.
509  */
510 static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
512         grab_common_values(val, deref, obj, buf, sz);
513         switch (obj->type) {
514         case OBJ_TAG:
515                 grab_tag_values(val, deref, obj, buf, sz);
516                 grab_sub_body_contents(val, deref, obj, buf, sz);
517                 grab_person("tagger", val, deref, obj, buf, sz);
518                 break;
519         case OBJ_COMMIT:
520                 grab_commit_values(val, deref, obj, buf, sz);
521                 grab_sub_body_contents(val, deref, obj, buf, sz);
522                 grab_person("author", val, deref, obj, buf, sz);
523                 grab_person("committer", val, deref, obj, buf, sz);
524                 break;
525         case OBJ_TREE:
526                 // grab_tree_values(val, deref, obj, buf, sz);
527                 break;
528         case OBJ_BLOB:
529                 // grab_blob_values(val, deref, obj, buf, sz);
530                 break;
531         default:
532                 die("Eh?  Object of type %d?", obj->type);
533         }
536 /*
537  * Parse the object referred by ref, and grab needed value.
538  */
539 static void populate_value(struct refinfo *ref)
541         void *buf;
542         struct object *obj;
543         int eaten, i;
544         unsigned long size;
545         const unsigned char *tagged;
547         ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
549         buf = get_obj(ref->objectname, &obj, &size, &eaten);
550         if (!buf)
551                 die("missing object %s for %s",
552                     sha1_to_hex(ref->objectname), ref->refname);
553         if (!obj)
554                 die("parse_object_buffer failed on %s for %s",
555                     sha1_to_hex(ref->objectname), ref->refname);
557         /* Fill in specials first */
558         for (i = 0; i < used_atom_cnt; i++) {
559                 const char *name = used_atom[i];
560                 struct atom_value *v = &ref->value[i];
561                 if (!strcmp(name, "refname"))
562                         v->s = ref->refname;
563                 else if (!strcmp(name, "*refname")) {
564                         int len = strlen(ref->refname);
565                         char *s = xmalloc(len + 4);
566                         sprintf(s, "%s^{}", ref->refname);
567                         v->s = s;
568                 }
569         }
571         grab_values(ref->value, 0, obj, buf, size);
572         if (!eaten)
573                 free(buf);
575         /* If there is no atom that wants to know about tagged
576          * object, we are done.
577          */
578         if (!need_tagged || (obj->type != OBJ_TAG))
579                 return;
581         /* If it is a tag object, see if we use a value that derefs
582          * the object, and if we do grab the object it refers to.
583          */
584         tagged = ((struct tag *)obj)->tagged->sha1;
586         /* NEEDSWORK: This derefs tag only once, which
587          * is good to deal with chains of trust, but
588          * is not consistent with what deref_tag() does
589          * which peels the onion to the core.
590          */
591         buf = get_obj(tagged, &obj, &size, &eaten);
592         if (!buf)
593                 die("missing object %s for %s",
594                     sha1_to_hex(tagged), ref->refname);
595         if (!obj)
596                 die("parse_object_buffer failed on %s for %s",
597                     sha1_to_hex(tagged), ref->refname);
598         grab_values(ref->value, 1, obj, buf, size);
599         if (!eaten)
600                 free(buf);
603 /*
604  * Given a ref, return the value for the atom.  This lazily gets value
605  * out of the object by calling populate value.
606  */
607 static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
609         if (!ref->value) {
610                 populate_value(ref);
611                 fill_missing_values(ref->value);
612         }
613         *v = &ref->value[atom];
616 struct grab_ref_cbdata {
617         struct refinfo **grab_array;
618         const char **grab_pattern;
619         int grab_cnt;
620 };
622 /*
623  * A call-back given to for_each_ref().  It is unfortunate that we
624  * need to use global variables to pass extra information to this
625  * function.
626  */
627 static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
629         struct grab_ref_cbdata *cb = cb_data;
630         struct refinfo *ref;
631         int cnt;
633         if (*cb->grab_pattern) {
634                 const char **pattern;
635                 int namelen = strlen(refname);
636                 for (pattern = cb->grab_pattern; *pattern; pattern++) {
637                         const char *p = *pattern;
638                         int plen = strlen(p);
640                         if ((plen <= namelen) &&
641                             !strncmp(refname, p, plen) &&
642                             (refname[plen] == '\0' ||
643                              refname[plen] == '/'))
644                                 break;
645                         if (!fnmatch(p, refname, FNM_PATHNAME))
646                                 break;
647                 }
648                 if (!*pattern)
649                         return 0;
650         }
652         /* We do not open the object yet; sort may only need refname
653          * to do its job and the resulting list may yet to be pruned
654          * by maxcount logic.
655          */
656         ref = xcalloc(1, sizeof(*ref));
657         ref->refname = xstrdup(refname);
658         hashcpy(ref->objectname, sha1);
660         cnt = cb->grab_cnt;
661         cb->grab_array = xrealloc(cb->grab_array,
662                                   sizeof(*cb->grab_array) * (cnt + 1));
663         cb->grab_array[cnt++] = ref;
664         cb->grab_cnt = cnt;
665         return 0;
668 static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
670         struct atom_value *va, *vb;
671         int cmp;
672         cmp_type cmp_type = used_atom_type[s->atom];
674         get_value(a, s->atom, &va);
675         get_value(b, s->atom, &vb);
676         switch (cmp_type) {
677         case FIELD_STR:
678                 cmp = strcmp(va->s, vb->s);
679                 break;
680         default:
681                 if (va->ul < vb->ul)
682                         cmp = -1;
683                 else if (va->ul == vb->ul)
684                         cmp = 0;
685                 else
686                         cmp = 1;
687                 break;
688         }
689         return (s->reverse) ? -cmp : cmp;
692 static struct ref_sort *ref_sort;
693 static int compare_refs(const void *a_, const void *b_)
695         struct refinfo *a = *((struct refinfo **)a_);
696         struct refinfo *b = *((struct refinfo **)b_);
697         struct ref_sort *s;
699         for (s = ref_sort; s; s = s->next) {
700                 int cmp = cmp_ref_sort(s, a, b);
701                 if (cmp)
702                         return cmp;
703         }
704         return 0;
707 static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
709         ref_sort = sort;
710         qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
713 static void print_value(struct refinfo *ref, int atom, int quote_style)
715         struct atom_value *v;
716         get_value(ref, atom, &v);
717         switch (quote_style) {
718         case QUOTE_NONE:
719                 fputs(v->s, stdout);
720                 break;
721         case QUOTE_SHELL:
722                 sq_quote_print(stdout, v->s);
723                 break;
724         case QUOTE_PERL:
725                 perl_quote_print(stdout, v->s);
726                 break;
727         case QUOTE_PYTHON:
728                 python_quote_print(stdout, v->s);
729                 break;
730         case QUOTE_TCL:
731                 tcl_quote_print(stdout, v->s);
732                 break;
733         }
736 static int hex1(char ch)
738         if ('0' <= ch && ch <= '9')
739                 return ch - '0';
740         else if ('a' <= ch && ch <= 'f')
741                 return ch - 'a' + 10;
742         else if ('A' <= ch && ch <= 'F')
743                 return ch - 'A' + 10;
744         return -1;
746 static int hex2(const char *cp)
748         if (cp[0] && cp[1])
749                 return (hex1(cp[0]) << 4) | hex1(cp[1]);
750         else
751                 return -1;
754 static void emit(const char *cp, const char *ep)
756         while (*cp && (!ep || cp < ep)) {
757                 if (*cp == '%') {
758                         if (cp[1] == '%')
759                                 cp++;
760                         else {
761                                 int ch = hex2(cp + 1);
762                                 if (0 <= ch) {
763                                         putchar(ch);
764                                         cp += 3;
765                                         continue;
766                                 }
767                         }
768                 }
769                 putchar(*cp);
770                 cp++;
771         }
774 static void show_ref(struct refinfo *info, const char *format, int quote_style)
776         const char *cp, *sp, *ep;
778         for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
779                 ep = strchr(sp, ')');
780                 if (cp < sp)
781                         emit(cp, sp);
782                 print_value(info, parse_atom(sp + 2, ep), quote_style);
783         }
784         if (*cp) {
785                 sp = cp + strlen(cp);
786                 emit(cp, sp);
787         }
788         putchar('\n');
791 static struct ref_sort *default_sort(void)
793         static const char cstr_name[] = "refname";
795         struct ref_sort *sort = xcalloc(1, sizeof(*sort));
797         sort->next = NULL;
798         sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
799         return sort;
802 int cmd_for_each_ref(int ac, const char **av, const char *prefix)
804         int i, num_refs;
805         const char *format = NULL;
806         struct ref_sort *sort = NULL, **sort_tail = &sort;
807         int maxcount = 0;
808         int quote_style = -1; /* unspecified yet */
809         struct refinfo **refs;
810         struct grab_ref_cbdata cbdata;
812         for (i = 1; i < ac; i++) {
813                 const char *arg = av[i];
814                 if (arg[0] != '-')
815                         break;
816                 if (!strcmp(arg, "--")) {
817                         i++;
818                         break;
819                 }
820                 if (!prefixcmp(arg, "--format=")) {
821                         if (format)
822                                 die("more than one --format?");
823                         format = arg + 9;
824                         continue;
825                 }
826                 if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
827                         if (0 <= quote_style)
828                                 die("more than one quoting style?");
829                         quote_style = QUOTE_SHELL;
830                         continue;
831                 }
832                 if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
833                         if (0 <= quote_style)
834                                 die("more than one quoting style?");
835                         quote_style = QUOTE_PERL;
836                         continue;
837                 }
838                 if (!strcmp(arg, "--python") ) {
839                         if (0 <= quote_style)
840                                 die("more than one quoting style?");
841                         quote_style = QUOTE_PYTHON;
842                         continue;
843                 }
844                 if (!strcmp(arg, "--tcl") ) {
845                         if (0 <= quote_style)
846                                 die("more than one quoting style?");
847                         quote_style = QUOTE_TCL;
848                         continue;
849                 }
850                 if (!prefixcmp(arg, "--count=")) {
851                         if (maxcount)
852                                 die("more than one --count?");
853                         maxcount = atoi(arg + 8);
854                         if (maxcount <= 0)
855                                 die("The number %s did not parse", arg);
856                         continue;
857                 }
858                 if (!prefixcmp(arg, "--sort=")) {
859                         struct ref_sort *s = xcalloc(1, sizeof(*s));
860                         int len;
862                         s->next = NULL;
863                         *sort_tail = s;
864                         sort_tail = &s->next;
866                         arg += 7;
867                         if (*arg == '-') {
868                                 s->reverse = 1;
869                                 arg++;
870                         }
871                         len = strlen(arg);
872                         sort->atom = parse_atom(arg, arg+len);
873                         continue;
874                 }
875                 break;
876         }
877         if (quote_style < 0)
878                 quote_style = QUOTE_NONE;
880         if (!sort)
881                 sort = default_sort();
882         sort_atom_limit = used_atom_cnt;
883         if (!format)
884                 format = "%(objectname) %(objecttype)\t%(refname)";
886         verify_format(format);
888         memset(&cbdata, 0, sizeof(cbdata));
889         cbdata.grab_pattern = av + i;
890         for_each_ref(grab_single_ref, &cbdata);
891         refs = cbdata.grab_array;
892         num_refs = cbdata.grab_cnt;
894         for (i = 0; i < used_atom_cnt; i++) {
895                 if (used_atom[i][0] == '*') {
896                         need_tagged = 1;
897                         break;
898                 }
899         }
901         sort_refs(sort, refs, num_refs);
903         if (!maxcount || num_refs < maxcount)
904                 maxcount = num_refs;
905         for (i = 0; i < maxcount; i++)
906                 show_ref(refs[i], format, quote_style);
907         return 0;