]> git.ipfire.org Git - thirdparty/git.git/blame - builtin-for-each-ref.c
git-clone.txt: Improve --depth description.
[thirdparty/git.git] / builtin-for-each-ref.c
CommitLineData
baffc0e7 1#include "builtin.h"
9f613ddd
JH
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"
9f613ddd
JH
10
11/* Quoting styles */
12#define QUOTE_NONE 0
13#define QUOTE_SHELL 1
14#define QUOTE_PERL 2
15#define QUOTE_PYTHON 3
5558e55c 16#define QUOTE_TCL 4
9f613ddd
JH
17
18typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
19
20struct atom_value {
21 const char *s;
22 unsigned long ul; /* used for sorting when not FIELD_STR */
23};
24
25struct ref_sort {
26 struct ref_sort *next;
27 int atom; /* index into used_atom array */
28 unsigned reverse : 1;
29};
30
31struct refinfo {
32 char *refname;
33 unsigned char objectname[20];
34 struct atom_value *value;
35};
36
37static 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" },
9e1a2acf 46 { "parent" },
9f613ddd
JH
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 },
3175aa1e
JH
63 { "creator" },
64 { "creatordate", FIELD_TIME },
9f613ddd
JH
65 { "subject" },
66 { "body" },
67 { "contents" },
68};
69
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 */
80static const char **used_atom;
81static cmp_type *used_atom_type;
82static int used_atom_cnt, sort_atom_limit, need_tagged;
83
84/*
85 * Used to parse format string and sort specifiers
86 */
87static int parse_atom(const char *atom, const char *ep)
88{
89 const char *sp;
90 char *n;
91 int i, at;
92
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);
98
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 }
105
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 }
112
113 if (ARRAY_SIZE(valid_atom) <= i)
114 die("unknown field name: %.*s", (int)(ep-atom), atom);
115
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;
129}
130
131/*
132 * In a format string, find the next occurrence of %(atom).
133 */
134static const char *find_next(const char *cp)
135{
136 while (*cp) {
137 if (*cp == '%') {
138 /* %( is the start of an atom;
3dff5379 139 * %% is a quoted per-cent.
9f613ddd
JH
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;
150}
151
152/*
153 * Make sure the format string is well formed, and parse out
154 * the used atoms.
155 */
156static void verify_format(const char *format)
157{
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 }
167}
168
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 */
175static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
176{
21666f1a
NP
177 enum object_type type;
178 void *buf = read_sha1_file(sha1, &type, sz);
9f613ddd
JH
179
180 if (buf)
181 *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
182 else
183 *obj = NULL;
184 return buf;
185}
186
187/* See grab_values */
188static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
189{
190 int i;
191
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"))
df843662 200 v->s = typename(obj->type);
9f613ddd
JH
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 }
213}
214
215/* See grab_values */
216static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
217{
218 int i;
219 struct tag *tag = (struct tag *) obj;
220
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 }
231}
232
233static int num_parents(struct commit *commit)
234{
235 struct commit_list *parents;
236 int i;
237
238 for (i = 0, parents = commit->parents;
239 parents;
240 parents = parents->next)
241 i++;
242 return i;
243}
244
245/* See grab_values */
246static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
247{
248 int i;
249 struct commit *commit = (struct commit *) obj;
250
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);
9e1a2acf 265 v->ul = num_parents(commit);
9f613ddd
JH
266 sprintf(s, "%lu", v->ul);
267 v->s = s;
9f613ddd
JH
268 }
269 else if (!strcmp(name, "parent")) {
270 int num = num_parents(commit);
271 int i;
272 struct commit_list *parents;
9e1a2acf 273 char *s = xmalloc(41 * num + 1);
9f613ddd
JH
274 v->s = s;
275 for (i = 0, parents = commit->parents;
276 parents;
9e1a2acf 277 parents = parents->next, i = i + 41) {
9f613ddd
JH
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 }
9e1a2acf
JH
283 if (!i)
284 *s = '\0';
9f613ddd
JH
285 }
286 }
287}
288
289static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
290{
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 "";
305}
306
3a55602e 307static const char *copy_line(const char *buf)
9f613ddd
JH
308{
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;
319}
320
3a55602e 321static const char *copy_name(const char *buf)
9f613ddd
JH
322{
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;
334}
335
3a55602e 336static const char *copy_email(const char *buf)
9f613ddd
JH
337{
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;
350}
351
352static void grab_date(const char *buf, struct atom_value *v)
353{
354 const char *eoemail = strstr(buf, "> ");
355 char *zone;
356 unsigned long timestamp;
357 long tz;
358
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;
373}
374
375/* See grab_values */
376static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
377{
378 int i;
379 int wholen = strlen(who);
380 const char *wholine = NULL;
381
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 }
3175aa1e
JH
409
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++;
426
427 if (!strcmp(name, "creatordate"))
428 grab_date(wholine, v);
429 else if (!strcmp(name, "creator"))
430 v->s = copy_line(wholine);
431 }
9f613ddd
JH
432}
433
434static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
435{
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;
457}
458
459/* See grab_values */
460static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
461{
462 int i;
463 const char *subpos = NULL, *bodypos = NULL;
464
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;
480
481 if (!strcmp(name, "subject"))
482 v->s = copy_line(subpos);
483 else if (!strcmp(name, "body"))
f8290630 484 v->s = xstrdup(bodypos);
9f613ddd 485 else if (!strcmp(name, "contents"))
f8290630 486 v->s = xstrdup(subpos);
9f613ddd
JH
487 }
488}
489
490/* We want to have empty print-string for field requests
491 * that do not apply (e.g. "authordate" for a tag object)
492 */
493static void fill_missing_values(struct atom_value *val)
494{
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 }
501}
502
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 */
510static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
511{
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 }
534}
535
536/*
537 * Parse the object referred by ref, and grab needed value.
538 */
539static void populate_value(struct refinfo *ref)
540{
541 void *buf;
542 struct object *obj;
543 int eaten, i;
544 unsigned long size;
545 const unsigned char *tagged;
546
547 ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
548
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);
556
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 }
570
571 grab_values(ref->value, 0, obj, buf, size);
572 if (!eaten)
573 free(buf);
574
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;
580
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;
585
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);
601}
602
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 */
607static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
608{
609 if (!ref->value) {
610 populate_value(ref);
611 fill_missing_values(ref->value);
612 }
613 *v = &ref->value[atom];
614}
615
340adb8b
JH
616struct grab_ref_cbdata {
617 struct refinfo **grab_array;
618 const char **grab_pattern;
619 int grab_cnt;
620};
9f613ddd
JH
621
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 */
340adb8b 627static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
9f613ddd 628{
340adb8b 629 struct grab_ref_cbdata *cb = cb_data;
9f613ddd
JH
630 struct refinfo *ref;
631 int cnt;
632
340adb8b 633 if (*cb->grab_pattern) {
9f613ddd
JH
634 const char **pattern;
635 int namelen = strlen(refname);
340adb8b 636 for (pattern = cb->grab_pattern; *pattern; pattern++) {
9f613ddd
JH
637 const char *p = *pattern;
638 int plen = strlen(p);
639
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 }
651
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);
659
340adb8b
JH
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;
9f613ddd
JH
665 return 0;
666}
667
9f613ddd
JH
668static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
669{
670 struct atom_value *va, *vb;
671 int cmp;
672 cmp_type cmp_type = used_atom_type[s->atom];
673
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;
690}
691
692static struct ref_sort *ref_sort;
693static int compare_refs(const void *a_, const void *b_)
694{
695 struct refinfo *a = *((struct refinfo **)a_);
696 struct refinfo *b = *((struct refinfo **)b_);
697 struct ref_sort *s;
698
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;
705}
706
707static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
708{
709 ref_sort = sort;
710 qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
711}
712
713static void print_value(struct refinfo *ref, int atom, int quote_style)
714{
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;
5558e55c
SP
730 case QUOTE_TCL:
731 tcl_quote_print(stdout, v->s);
732 break;
9f613ddd
JH
733 }
734}
735
736static int hex1(char ch)
737{
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;
745}
746static int hex2(const char *cp)
747{
748 if (cp[0] && cp[1])
749 return (hex1(cp[0]) << 4) | hex1(cp[1]);
750 else
751 return -1;
752}
753
754static void emit(const char *cp, const char *ep)
755{
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 }
772}
773
774static void show_ref(struct refinfo *info, const char *format, int quote_style)
775{
776 const char *cp, *sp, *ep;
777
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');
789}
790
791static struct ref_sort *default_sort(void)
792{
793 static const char cstr_name[] = "refname";
794
795 struct ref_sort *sort = xcalloc(1, sizeof(*sort));
796
797 sort->next = NULL;
798 sort->atom = parse_atom(cstr_name, cstr_name + strlen(cstr_name));
799 return sort;
800}
801
baffc0e7 802int cmd_for_each_ref(int ac, const char **av, const char *prefix)
9f613ddd
JH
803{
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;
340adb8b 810 struct grab_ref_cbdata cbdata;
9f613ddd
JH
811
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 }
cc44c765 820 if (!prefixcmp(arg, "--format=")) {
9f613ddd
JH
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 }
5558e55c
SP
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 }
cc44c765 850 if (!prefixcmp(arg, "--count=")) {
9f613ddd
JH
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 }
cc44c765 858 if (!prefixcmp(arg, "--sort=")) {
9f613ddd
JH
859 struct ref_sort *s = xcalloc(1, sizeof(*s));
860 int len;
861
862 s->next = NULL;
863 *sort_tail = s;
864 sort_tail = &s->next;
865
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;
879
880 if (!sort)
881 sort = default_sort();
882 sort_atom_limit = used_atom_cnt;
883 if (!format)
884 format = "%(objectname) %(objecttype)\t%(refname)";
885
886 verify_format(format);
887
340adb8b
JH
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;
9f613ddd
JH
893
894 for (i = 0; i < used_atom_cnt; i++) {
895 if (used_atom[i][0] == '*') {
896 need_tagged = 1;
897 break;
898 }
899 }
900
901 sort_refs(sort, refs, num_refs);
902
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;
908}