Merge branch 'js/rebase-i'
[git/jnareb-git.git] / builtin-for-each-ref.c
blob5dbf3e59f297b1849c1289b7cc7980bddf1852f7
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 */
25 struct ref_sort {
26 struct ref_sort *next;
27 int atom; /* index into used_atom array */
28 unsigned reverse : 1;
31 struct refinfo {
32 char *refname;
33 unsigned char objectname[20];
34 struct atom_value *value;
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" },
71 * An atom is a valid field atom listed above, possibly prefixed with
72 * a "*" to denote deref_tag().
74 * We parse given format string and sort specifiers, and make a list
75 * of properties that we need to extract out of objects. refinfo
76 * structure will hold an array of values extracted that can be
77 * indexed with the "atom number", which is an index into this
78 * array.
80 static const char **used_atom;
81 static cmp_type *used_atom_type;
82 static int used_atom_cnt, sort_atom_limit, need_tagged;
85 * Used to parse format string and sort specifiers
87 static int parse_atom(const char *atom, const char *ep)
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;
106 /* Is the atom a valid one? */
107 for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
108 int len = strlen(valid_atom[i].name);
110 * If the atom name has a colon, strip it and everything after
111 * it off - it specifies the format for this entry, and
112 * shouldn't be used for checking against the valid_atom
113 * table.
115 const char *formatp = strchr(sp, ':');
116 if (!formatp || ep < formatp)
117 formatp = ep;
118 if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
119 break;
122 if (ARRAY_SIZE(valid_atom) <= i)
123 die("unknown field name: %.*s", (int)(ep-atom), atom);
125 /* Add it in, including the deref prefix */
126 at = used_atom_cnt;
127 used_atom_cnt++;
128 used_atom = xrealloc(used_atom,
129 (sizeof *used_atom) * used_atom_cnt);
130 used_atom_type = xrealloc(used_atom_type,
131 (sizeof(*used_atom_type) * used_atom_cnt));
132 n = xmalloc(ep - atom + 1);
133 memcpy(n, atom, ep - atom);
134 n[ep-atom] = 0;
135 used_atom[at] = n;
136 used_atom_type[at] = valid_atom[i].cmp_type;
137 return at;
141 * In a format string, find the next occurrence of %(atom).
143 static const char *find_next(const char *cp)
145 while (*cp) {
146 if (*cp == '%') {
147 /* %( is the start of an atom;
148 * %% is a quoted per-cent.
150 if (cp[1] == '(')
151 return cp;
152 else if (cp[1] == '%')
153 cp++; /* skip over two % */
154 /* otherwise this is a singleton, literal % */
156 cp++;
158 return NULL;
162 * Make sure the format string is well formed, and parse out
163 * the used atoms.
165 static void verify_format(const char *format)
167 const char *cp, *sp;
168 for (cp = format; *cp && (sp = find_next(cp)); ) {
169 const char *ep = strchr(sp, ')');
170 if (!ep)
171 die("malformatted format string %s", sp);
172 /* sp points at "%(" and ep points at the closing ")" */
173 parse_atom(sp + 2, ep);
174 cp = ep + 1;
179 * Given an object name, read the object data and size, and return a
180 * "struct object". If the object data we are returning is also borrowed
181 * by the "struct object" representation, set *eaten as well---it is a
182 * signal from parse_object_buffer to us not to free the buffer.
184 static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
186 enum object_type type;
187 void *buf = read_sha1_file(sha1, &type, sz);
189 if (buf)
190 *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
191 else
192 *obj = NULL;
193 return buf;
196 /* See grab_values */
197 static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
199 int i;
201 for (i = 0; i < used_atom_cnt; i++) {
202 const char *name = used_atom[i];
203 struct atom_value *v = &val[i];
204 if (!!deref != (*name == '*'))
205 continue;
206 if (deref)
207 name++;
208 if (!strcmp(name, "objecttype"))
209 v->s = typename(obj->type);
210 else if (!strcmp(name, "objectsize")) {
211 char *s = xmalloc(40);
212 sprintf(s, "%lu", sz);
213 v->ul = sz;
214 v->s = s;
216 else if (!strcmp(name, "objectname")) {
217 char *s = xmalloc(41);
218 strcpy(s, sha1_to_hex(obj->sha1));
219 v->s = s;
224 /* See grab_values */
225 static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
227 int i;
228 struct tag *tag = (struct tag *) obj;
230 for (i = 0; i < used_atom_cnt; i++) {
231 const char *name = used_atom[i];
232 struct atom_value *v = &val[i];
233 if (!!deref != (*name == '*'))
234 continue;
235 if (deref)
236 name++;
237 if (!strcmp(name, "tag"))
238 v->s = tag->tag;
242 static int num_parents(struct commit *commit)
244 struct commit_list *parents;
245 int i;
247 for (i = 0, parents = commit->parents;
248 parents;
249 parents = parents->next)
250 i++;
251 return i;
254 /* See grab_values */
255 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
257 int i;
258 struct commit *commit = (struct commit *) obj;
260 for (i = 0; i < used_atom_cnt; i++) {
261 const char *name = used_atom[i];
262 struct atom_value *v = &val[i];
263 if (!!deref != (*name == '*'))
264 continue;
265 if (deref)
266 name++;
267 if (!strcmp(name, "tree")) {
268 char *s = xmalloc(41);
269 strcpy(s, sha1_to_hex(commit->tree->object.sha1));
270 v->s = s;
272 if (!strcmp(name, "numparent")) {
273 char *s = xmalloc(40);
274 v->ul = num_parents(commit);
275 sprintf(s, "%lu", v->ul);
276 v->s = s;
278 else if (!strcmp(name, "parent")) {
279 int num = num_parents(commit);
280 int i;
281 struct commit_list *parents;
282 char *s = xmalloc(41 * num + 1);
283 v->s = s;
284 for (i = 0, parents = commit->parents;
285 parents;
286 parents = parents->next, i = i + 41) {
287 struct commit *parent = parents->item;
288 strcpy(s+i, sha1_to_hex(parent->object.sha1));
289 if (parents->next)
290 s[i+40] = ' ';
292 if (!i)
293 *s = '\0';
298 static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
300 const char *eol;
301 while (*buf) {
302 if (!strncmp(buf, who, wholen) &&
303 buf[wholen] == ' ')
304 return buf + wholen + 1;
305 eol = strchr(buf, '\n');
306 if (!eol)
307 return "";
308 eol++;
309 if (eol[1] == '\n')
310 return ""; /* end of header */
311 buf = eol;
313 return "";
316 static const char *copy_line(const char *buf)
318 const char *eol = strchr(buf, '\n');
319 char *line;
320 int len;
321 if (!eol)
322 return "";
323 len = eol - buf;
324 line = xmalloc(len + 1);
325 memcpy(line, buf, len);
326 line[len] = 0;
327 return line;
330 static const char *copy_name(const char *buf)
332 const char *eol = strchr(buf, '\n');
333 const char *eoname = strstr(buf, " <");
334 char *line;
335 int len;
336 if (!(eoname && eol && eoname < eol))
337 return "";
338 len = eoname - buf;
339 line = xmalloc(len + 1);
340 memcpy(line, buf, len);
341 line[len] = 0;
342 return line;
345 static const char *copy_email(const char *buf)
347 const char *email = strchr(buf, '<');
348 const char *eoemail = strchr(email, '>');
349 char *line;
350 int len;
351 if (!email || !eoemail)
352 return "";
353 eoemail++;
354 len = eoemail - email;
355 line = xmalloc(len + 1);
356 memcpy(line, email, len);
357 line[len] = 0;
358 return line;
361 static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
363 const char *eoemail = strstr(buf, "> ");
364 char *zone;
365 unsigned long timestamp;
366 long tz;
367 enum date_mode date_mode = DATE_NORMAL;
368 const char *formatp;
371 * We got here because atomname ends in "date" or "date<something>";
372 * it's not possible that <something> is not ":<format>" because
373 * parse_atom() wouldn't have allowed it, so we can assume that no
374 * ":" means no format is specified, and use the default.
376 formatp = strchr(atomname, ':');
377 if (formatp != NULL) {
378 formatp++;
379 date_mode = parse_date_format(formatp);
382 if (!eoemail)
383 goto bad;
384 timestamp = strtoul(eoemail + 2, &zone, 10);
385 if (timestamp == ULONG_MAX)
386 goto bad;
387 tz = strtol(zone, NULL, 10);
388 if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
389 goto bad;
390 v->s = xstrdup(show_date(timestamp, tz, date_mode));
391 v->ul = timestamp;
392 return;
393 bad:
394 v->s = "";
395 v->ul = 0;
398 /* See grab_values */
399 static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
401 int i;
402 int wholen = strlen(who);
403 const char *wholine = NULL;
405 for (i = 0; i < used_atom_cnt; i++) {
406 const char *name = used_atom[i];
407 struct atom_value *v = &val[i];
408 if (!!deref != (*name == '*'))
409 continue;
410 if (deref)
411 name++;
412 if (strncmp(who, name, wholen))
413 continue;
414 if (name[wholen] != 0 &&
415 strcmp(name + wholen, "name") &&
416 strcmp(name + wholen, "email") &&
417 prefixcmp(name + wholen, "date"))
418 continue;
419 if (!wholine)
420 wholine = find_wholine(who, wholen, buf, sz);
421 if (!wholine)
422 return; /* no point looking for it */
423 if (name[wholen] == 0)
424 v->s = copy_line(wholine);
425 else if (!strcmp(name + wholen, "name"))
426 v->s = copy_name(wholine);
427 else if (!strcmp(name + wholen, "email"))
428 v->s = copy_email(wholine);
429 else if (!prefixcmp(name + wholen, "date"))
430 grab_date(wholine, v, name);
433 /* For a tag or a commit object, if "creator" or "creatordate" is
434 * requested, do something special.
436 if (strcmp(who, "tagger") && strcmp(who, "committer"))
437 return; /* "author" for commit object is not wanted */
438 if (!wholine)
439 wholine = find_wholine(who, wholen, buf, sz);
440 if (!wholine)
441 return;
442 for (i = 0; i < used_atom_cnt; i++) {
443 const char *name = used_atom[i];
444 struct atom_value *v = &val[i];
445 if (!!deref != (*name == '*'))
446 continue;
447 if (deref)
448 name++;
450 if (!prefixcmp(name, "creatordate"))
451 grab_date(wholine, v, name);
452 else if (!strcmp(name, "creator"))
453 v->s = copy_line(wholine);
457 static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
459 while (*buf) {
460 const char *eol = strchr(buf, '\n');
461 if (!eol)
462 return;
463 if (eol[1] == '\n') {
464 buf = eol + 1;
465 break; /* found end of header */
467 buf = eol + 1;
469 while (*buf == '\n')
470 buf++;
471 if (!*buf)
472 return;
473 *sub = buf; /* first non-empty line */
474 buf = strchr(buf, '\n');
475 if (!buf)
476 return; /* no body */
477 while (*buf == '\n')
478 buf++; /* skip blank between subject and body */
479 *body = buf;
482 /* See grab_values */
483 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
485 int i;
486 const char *subpos = NULL, *bodypos = NULL;
488 for (i = 0; i < used_atom_cnt; i++) {
489 const char *name = used_atom[i];
490 struct atom_value *v = &val[i];
491 if (!!deref != (*name == '*'))
492 continue;
493 if (deref)
494 name++;
495 if (strcmp(name, "subject") &&
496 strcmp(name, "body") &&
497 strcmp(name, "contents"))
498 continue;
499 if (!subpos)
500 find_subpos(buf, sz, &subpos, &bodypos);
501 if (!subpos)
502 return;
504 if (!strcmp(name, "subject"))
505 v->s = copy_line(subpos);
506 else if (!strcmp(name, "body"))
507 v->s = xstrdup(bodypos);
508 else if (!strcmp(name, "contents"))
509 v->s = xstrdup(subpos);
513 /* We want to have empty print-string for field requests
514 * that do not apply (e.g. "authordate" for a tag object)
516 static void fill_missing_values(struct atom_value *val)
518 int i;
519 for (i = 0; i < used_atom_cnt; i++) {
520 struct atom_value *v = &val[i];
521 if (v->s == NULL)
522 v->s = "";
527 * val is a list of atom_value to hold returned values. Extract
528 * the values for atoms in used_atom array out of (obj, buf, sz).
529 * when deref is false, (obj, buf, sz) is the object that is
530 * pointed at by the ref itself; otherwise it is the object the
531 * ref (which is a tag) refers to.
533 static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
535 grab_common_values(val, deref, obj, buf, sz);
536 switch (obj->type) {
537 case OBJ_TAG:
538 grab_tag_values(val, deref, obj, buf, sz);
539 grab_sub_body_contents(val, deref, obj, buf, sz);
540 grab_person("tagger", val, deref, obj, buf, sz);
541 break;
542 case OBJ_COMMIT:
543 grab_commit_values(val, deref, obj, buf, sz);
544 grab_sub_body_contents(val, deref, obj, buf, sz);
545 grab_person("author", val, deref, obj, buf, sz);
546 grab_person("committer", val, deref, obj, buf, sz);
547 break;
548 case OBJ_TREE:
549 // grab_tree_values(val, deref, obj, buf, sz);
550 break;
551 case OBJ_BLOB:
552 // grab_blob_values(val, deref, obj, buf, sz);
553 break;
554 default:
555 die("Eh? Object of type %d?", obj->type);
560 * Parse the object referred by ref, and grab needed value.
562 static void populate_value(struct refinfo *ref)
564 void *buf;
565 struct object *obj;
566 int eaten, i;
567 unsigned long size;
568 const unsigned char *tagged;
570 ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
572 buf = get_obj(ref->objectname, &obj, &size, &eaten);
573 if (!buf)
574 die("missing object %s for %s",
575 sha1_to_hex(ref->objectname), ref->refname);
576 if (!obj)
577 die("parse_object_buffer failed on %s for %s",
578 sha1_to_hex(ref->objectname), ref->refname);
580 /* Fill in specials first */
581 for (i = 0; i < used_atom_cnt; i++) {
582 const char *name = used_atom[i];
583 struct atom_value *v = &ref->value[i];
584 if (!strcmp(name, "refname"))
585 v->s = ref->refname;
586 else if (!strcmp(name, "*refname")) {
587 int len = strlen(ref->refname);
588 char *s = xmalloc(len + 4);
589 sprintf(s, "%s^{}", ref->refname);
590 v->s = s;
594 grab_values(ref->value, 0, obj, buf, size);
595 if (!eaten)
596 free(buf);
598 /* If there is no atom that wants to know about tagged
599 * object, we are done.
601 if (!need_tagged || (obj->type != OBJ_TAG))
602 return;
604 /* If it is a tag object, see if we use a value that derefs
605 * the object, and if we do grab the object it refers to.
607 tagged = ((struct tag *)obj)->tagged->sha1;
609 /* NEEDSWORK: This derefs tag only once, which
610 * is good to deal with chains of trust, but
611 * is not consistent with what deref_tag() does
612 * which peels the onion to the core.
614 buf = get_obj(tagged, &obj, &size, &eaten);
615 if (!buf)
616 die("missing object %s for %s",
617 sha1_to_hex(tagged), ref->refname);
618 if (!obj)
619 die("parse_object_buffer failed on %s for %s",
620 sha1_to_hex(tagged), ref->refname);
621 grab_values(ref->value, 1, obj, buf, size);
622 if (!eaten)
623 free(buf);
627 * Given a ref, return the value for the atom. This lazily gets value
628 * out of the object by calling populate value.
630 static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
632 if (!ref->value) {
633 populate_value(ref);
634 fill_missing_values(ref->value);
636 *v = &ref->value[atom];
639 struct grab_ref_cbdata {
640 struct refinfo **grab_array;
641 const char **grab_pattern;
642 int grab_cnt;
646 * A call-back given to for_each_ref(). It is unfortunate that we
647 * need to use global variables to pass extra information to this
648 * function.
650 static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
652 struct grab_ref_cbdata *cb = cb_data;
653 struct refinfo *ref;
654 int cnt;
656 if (*cb->grab_pattern) {
657 const char **pattern;
658 int namelen = strlen(refname);
659 for (pattern = cb->grab_pattern; *pattern; pattern++) {
660 const char *p = *pattern;
661 int plen = strlen(p);
663 if ((plen <= namelen) &&
664 !strncmp(refname, p, plen) &&
665 (refname[plen] == '\0' ||
666 refname[plen] == '/'))
667 break;
668 if (!fnmatch(p, refname, FNM_PATHNAME))
669 break;
671 if (!*pattern)
672 return 0;
675 /* We do not open the object yet; sort may only need refname
676 * to do its job and the resulting list may yet to be pruned
677 * by maxcount logic.
679 ref = xcalloc(1, sizeof(*ref));
680 ref->refname = xstrdup(refname);
681 hashcpy(ref->objectname, sha1);
683 cnt = cb->grab_cnt;
684 cb->grab_array = xrealloc(cb->grab_array,
685 sizeof(*cb->grab_array) * (cnt + 1));
686 cb->grab_array[cnt++] = ref;
687 cb->grab_cnt = cnt;
688 return 0;
691 static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
693 struct atom_value *va, *vb;
694 int cmp;
695 cmp_type cmp_type = used_atom_type[s->atom];
697 get_value(a, s->atom, &va);
698 get_value(b, s->atom, &vb);
699 switch (cmp_type) {
700 case FIELD_STR:
701 cmp = strcmp(va->s, vb->s);
702 break;
703 default:
704 if (va->ul < vb->ul)
705 cmp = -1;
706 else if (va->ul == vb->ul)
707 cmp = 0;
708 else
709 cmp = 1;
710 break;
712 return (s->reverse) ? -cmp : cmp;
715 static struct ref_sort *ref_sort;
716 static int compare_refs(const void *a_, const void *b_)
718 struct refinfo *a = *((struct refinfo **)a_);
719 struct refinfo *b = *((struct refinfo **)b_);
720 struct ref_sort *s;
722 for (s = ref_sort; s; s = s->next) {
723 int cmp = cmp_ref_sort(s, a, b);
724 if (cmp)
725 return cmp;
727 return 0;
730 static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
732 ref_sort = sort;
733 qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
736 static void print_value(struct refinfo *ref, int atom, int quote_style)
738 struct atom_value *v;
739 get_value(ref, atom, &v);
740 switch (quote_style) {
741 case QUOTE_NONE:
742 fputs(v->s, stdout);
743 break;
744 case QUOTE_SHELL:
745 sq_quote_print(stdout, v->s);
746 break;
747 case QUOTE_PERL:
748 perl_quote_print(stdout, v->s);
749 break;
750 case QUOTE_PYTHON:
751 python_quote_print(stdout, v->s);
752 break;
753 case QUOTE_TCL:
754 tcl_quote_print(stdout, v->s);
755 break;
759 static int hex1(char ch)
761 if ('0' <= ch && ch <= '9')
762 return ch - '0';
763 else if ('a' <= ch && ch <= 'f')
764 return ch - 'a' + 10;
765 else if ('A' <= ch && ch <= 'F')
766 return ch - 'A' + 10;
767 return -1;
769 static int hex2(const char *cp)
771 if (cp[0] && cp[1])
772 return (hex1(cp[0]) << 4) | hex1(cp[1]);
773 else
774 return -1;
777 static void emit(const char *cp, const char *ep)
779 while (*cp && (!ep || cp < ep)) {
780 if (*cp == '%') {
781 if (cp[1] == '%')
782 cp++;
783 else {
784 int ch = hex2(cp + 1);
785 if (0 <= ch) {
786 putchar(ch);
787 cp += 3;
788 continue;
792 putchar(*cp);
793 cp++;
797 static void show_ref(struct refinfo *info, const char *format, int quote_style)
799 const char *cp, *sp, *ep;
801 for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
802 ep = strchr(sp, ')');
803 if (cp < sp)
804 emit(cp, sp);
805 print_value(info, parse_atom(sp + 2, ep), quote_style);
807 if (*cp) {
808 sp = cp + strlen(cp);
809 emit(cp, sp);
811 putchar('\n');
814 static struct ref_sort *default_sort(void)
816 static const char cstr_name[] = "refname";
818 struct ref_sort *sort = xcalloc(1, sizeof(*sort));
820 sort->next = NULL;
821 sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
822 return sort;
825 int cmd_for_each_ref(int ac, const char **av, const char *prefix)
827 int i, num_refs;
828 const char *format = NULL;
829 struct ref_sort *sort = NULL, **sort_tail = &sort;
830 int maxcount = 0;
831 int quote_style = -1; /* unspecified yet */
832 struct refinfo **refs;
833 struct grab_ref_cbdata cbdata;
835 for (i = 1; i < ac; i++) {
836 const char *arg = av[i];
837 if (arg[0] != '-')
838 break;
839 if (!strcmp(arg, "--")) {
840 i++;
841 break;
843 if (!prefixcmp(arg, "--format=")) {
844 if (format)
845 die("more than one --format?");
846 format = arg + 9;
847 continue;
849 if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
850 if (0 <= quote_style)
851 die("more than one quoting style?");
852 quote_style = QUOTE_SHELL;
853 continue;
855 if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
856 if (0 <= quote_style)
857 die("more than one quoting style?");
858 quote_style = QUOTE_PERL;
859 continue;
861 if (!strcmp(arg, "--python") ) {
862 if (0 <= quote_style)
863 die("more than one quoting style?");
864 quote_style = QUOTE_PYTHON;
865 continue;
867 if (!strcmp(arg, "--tcl") ) {
868 if (0 <= quote_style)
869 die("more than one quoting style?");
870 quote_style = QUOTE_TCL;
871 continue;
873 if (!prefixcmp(arg, "--count=")) {
874 if (maxcount)
875 die("more than one --count?");
876 maxcount = atoi(arg + 8);
877 if (maxcount <= 0)
878 die("The number %s did not parse", arg);
879 continue;
881 if (!prefixcmp(arg, "--sort=")) {
882 struct ref_sort *s = xcalloc(1, sizeof(*s));
883 int len;
885 s->next = NULL;
886 *sort_tail = s;
887 sort_tail = &s->next;
889 arg += 7;
890 if (*arg == '-') {
891 s->reverse = 1;
892 arg++;
894 len = strlen(arg);
895 sort->atom = parse_atom(arg, arg+len);
896 continue;
898 break;
900 if (quote_style < 0)
901 quote_style = QUOTE_NONE;
903 if (!sort)
904 sort = default_sort();
905 sort_atom_limit = used_atom_cnt;
906 if (!format)
907 format = "%(objectname) %(objecttype)\t%(refname)";
909 verify_format(format);
911 memset(&cbdata, 0, sizeof(cbdata));
912 cbdata.grab_pattern = av + i;
913 for_each_ref(grab_single_ref, &cbdata);
914 refs = cbdata.grab_array;
915 num_refs = cbdata.grab_cnt;
917 for (i = 0; i < used_atom_cnt; i++) {
918 if (used_atom[i][0] == '*') {
919 need_tagged = 1;
920 break;
924 sort_refs(sort, refs, num_refs);
926 if (!maxcount || num_refs < maxcount)
927 maxcount = num_refs;
928 for (i = 0; i < maxcount; i++)
929 show_ref(refs[i], format, quote_style);
930 return 0;