]> git.ipfire.org Git - thirdparty/git.git/blob - builtin-for-each-ref.c
Merge branch 'jc/for-each-ref-with-lt-refs' into jc/ref-locking
[thirdparty/git.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 struct grab_ref_cbdata {
589 struct refinfo **grab_array;
590 const char **grab_pattern;
591 int grab_cnt;
592 };
593
594 /*
595 * A call-back given to for_each_ref(). It is unfortunate that we
596 * need to use global variables to pass extra information to this
597 * function.
598 */
599 static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
600 {
601 struct grab_ref_cbdata *cb = cb_data;
602 struct refinfo *ref;
603 int cnt;
604
605 if (*cb->grab_pattern) {
606 const char **pattern;
607 int namelen = strlen(refname);
608 for (pattern = cb->grab_pattern; *pattern; pattern++) {
609 const char *p = *pattern;
610 int plen = strlen(p);
611
612 if ((plen <= namelen) &&
613 !strncmp(refname, p, plen) &&
614 (refname[plen] == '\0' ||
615 refname[plen] == '/'))
616 break;
617 if (!fnmatch(p, refname, FNM_PATHNAME))
618 break;
619 }
620 if (!*pattern)
621 return 0;
622 }
623
624 /* We do not open the object yet; sort may only need refname
625 * to do its job and the resulting list may yet to be pruned
626 * by maxcount logic.
627 */
628 ref = xcalloc(1, sizeof(*ref));
629 ref->refname = xstrdup(refname);
630 hashcpy(ref->objectname, sha1);
631
632 cnt = cb->grab_cnt;
633 cb->grab_array = xrealloc(cb->grab_array,
634 sizeof(*cb->grab_array) * (cnt + 1));
635 cb->grab_array[cnt++] = ref;
636 cb->grab_cnt = cnt;
637 return 0;
638 }
639
640 static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
641 {
642 struct atom_value *va, *vb;
643 int cmp;
644 cmp_type cmp_type = used_atom_type[s->atom];
645
646 get_value(a, s->atom, &va);
647 get_value(b, s->atom, &vb);
648 switch (cmp_type) {
649 case FIELD_STR:
650 cmp = strcmp(va->s, vb->s);
651 break;
652 default:
653 if (va->ul < vb->ul)
654 cmp = -1;
655 else if (va->ul == vb->ul)
656 cmp = 0;
657 else
658 cmp = 1;
659 break;
660 }
661 return (s->reverse) ? -cmp : cmp;
662 }
663
664 static struct ref_sort *ref_sort;
665 static int compare_refs(const void *a_, const void *b_)
666 {
667 struct refinfo *a = *((struct refinfo **)a_);
668 struct refinfo *b = *((struct refinfo **)b_);
669 struct ref_sort *s;
670
671 for (s = ref_sort; s; s = s->next) {
672 int cmp = cmp_ref_sort(s, a, b);
673 if (cmp)
674 return cmp;
675 }
676 return 0;
677 }
678
679 static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
680 {
681 ref_sort = sort;
682 qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
683 }
684
685 static void print_value(struct refinfo *ref, int atom, int quote_style)
686 {
687 struct atom_value *v;
688 get_value(ref, atom, &v);
689 switch (quote_style) {
690 case QUOTE_NONE:
691 fputs(v->s, stdout);
692 break;
693 case QUOTE_SHELL:
694 sq_quote_print(stdout, v->s);
695 break;
696 case QUOTE_PERL:
697 perl_quote_print(stdout, v->s);
698 break;
699 case QUOTE_PYTHON:
700 python_quote_print(stdout, v->s);
701 break;
702 }
703 }
704
705 static int hex1(char ch)
706 {
707 if ('0' <= ch && ch <= '9')
708 return ch - '0';
709 else if ('a' <= ch && ch <= 'f')
710 return ch - 'a' + 10;
711 else if ('A' <= ch && ch <= 'F')
712 return ch - 'A' + 10;
713 return -1;
714 }
715 static int hex2(const char *cp)
716 {
717 if (cp[0] && cp[1])
718 return (hex1(cp[0]) << 4) | hex1(cp[1]);
719 else
720 return -1;
721 }
722
723 static void emit(const char *cp, const char *ep)
724 {
725 while (*cp && (!ep || cp < ep)) {
726 if (*cp == '%') {
727 if (cp[1] == '%')
728 cp++;
729 else {
730 int ch = hex2(cp + 1);
731 if (0 <= ch) {
732 putchar(ch);
733 cp += 3;
734 continue;
735 }
736 }
737 }
738 putchar(*cp);
739 cp++;
740 }
741 }
742
743 static void show_ref(struct refinfo *info, const char *format, int quote_style)
744 {
745 const char *cp, *sp, *ep;
746
747 for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
748 ep = strchr(sp, ')');
749 if (cp < sp)
750 emit(cp, sp);
751 print_value(info, parse_atom(sp + 2, ep), quote_style);
752 }
753 if (*cp) {
754 sp = cp + strlen(cp);
755 emit(cp, sp);
756 }
757 putchar('\n');
758 }
759
760 static struct ref_sort *default_sort(void)
761 {
762 static const char cstr_name[] = "refname";
763
764 struct ref_sort *sort = xcalloc(1, sizeof(*sort));
765
766 sort->next = NULL;
767 sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
768 return sort;
769 }
770
771 int cmd_for_each_ref(int ac, const char **av, char *prefix)
772 {
773 int i, num_refs;
774 const char *format = NULL;
775 struct ref_sort *sort = NULL, **sort_tail = &sort;
776 int maxcount = 0;
777 int quote_style = -1; /* unspecified yet */
778 struct refinfo **refs;
779 struct grab_ref_cbdata cbdata;
780
781 for (i = 1; i < ac; i++) {
782 const char *arg = av[i];
783 if (arg[0] != '-')
784 break;
785 if (!strcmp(arg, "--")) {
786 i++;
787 break;
788 }
789 if (!strncmp(arg, "--format=", 9)) {
790 if (format)
791 die("more than one --format?");
792 format = arg + 9;
793 continue;
794 }
795 if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
796 if (0 <= quote_style)
797 die("more than one quoting style?");
798 quote_style = QUOTE_SHELL;
799 continue;
800 }
801 if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
802 if (0 <= quote_style)
803 die("more than one quoting style?");
804 quote_style = QUOTE_PERL;
805 continue;
806 }
807 if (!strcmp(arg, "--python") ) {
808 if (0 <= quote_style)
809 die("more than one quoting style?");
810 quote_style = QUOTE_PYTHON;
811 continue;
812 }
813 if (!strncmp(arg, "--count=", 8)) {
814 if (maxcount)
815 die("more than one --count?");
816 maxcount = atoi(arg + 8);
817 if (maxcount <= 0)
818 die("The number %s did not parse", arg);
819 continue;
820 }
821 if (!strncmp(arg, "--sort=", 7)) {
822 struct ref_sort *s = xcalloc(1, sizeof(*s));
823 int len;
824
825 s->next = NULL;
826 *sort_tail = s;
827 sort_tail = &s->next;
828
829 arg += 7;
830 if (*arg == '-') {
831 s->reverse = 1;
832 arg++;
833 }
834 len = strlen(arg);
835 sort->atom = parse_atom(arg, arg+len);
836 continue;
837 }
838 break;
839 }
840 if (quote_style < 0)
841 quote_style = QUOTE_NONE;
842
843 if (!sort)
844 sort = default_sort();
845 sort_atom_limit = used_atom_cnt;
846 if (!format)
847 format = "%(objectname) %(objecttype)\t%(refname)";
848
849 verify_format(format);
850
851 memset(&cbdata, 0, sizeof(cbdata));
852 cbdata.grab_pattern = av + i;
853 for_each_ref(grab_single_ref, &cbdata);
854 refs = cbdata.grab_array;
855 num_refs = cbdata.grab_cnt;
856
857 for (i = 0; i < used_atom_cnt; i++) {
858 if (used_atom[i][0] == '*') {
859 need_tagged = 1;
860 break;
861 }
862 }
863
864 sort_refs(sort, refs, num_refs);
865
866 if (!maxcount || num_refs < maxcount)
867 maxcount = num_refs;
868 for (i = 0; i < maxcount; i++)
869 show_ref(refs[i], format, quote_style);
870 return 0;
871 }