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