10 #include "parse-options.h"
13 #include "ref-filter.h"
15 typedef enum { FIELD_STR
, FIELD_ULONG
, FIELD_TIME
} cmp_type
;
23 { "objectsize", FIELD_ULONG
},
27 { "numparent", FIELD_ULONG
},
34 { "authordate", FIELD_TIME
},
38 { "committerdate", FIELD_TIME
},
42 { "taggerdate", FIELD_TIME
},
44 { "creatordate", FIELD_TIME
},
48 { "contents:subject" },
50 { "contents:signature" },
60 * An atom is a valid field atom listed above, possibly prefixed with
61 * a "*" to denote deref_tag().
63 * We parse given format string and sort specifiers, and make a list
64 * of properties that we need to extract out of objects. ref_array_item
65 * structure will hold an array of values extracted that can be
66 * indexed with the "atom number", which is an index into this
69 static const char **used_atom
;
70 static cmp_type
*used_atom_type
;
71 static int used_atom_cnt
, need_tagged
, need_symref
;
72 static int need_color_reset_at_eol
;
75 * Used to parse format string and sort specifiers
77 int parse_ref_filter_atom(const char *atom
, const char *ep
)
83 if (*sp
== '*' && sp
< ep
)
86 die("malformed field name: %.*s", (int)(ep
-atom
), atom
);
88 /* Do we have the atom already used elsewhere? */
89 for (i
= 0; i
< used_atom_cnt
; i
++) {
90 int len
= strlen(used_atom
[i
]);
91 if (len
== ep
- atom
&& !memcmp(used_atom
[i
], atom
, len
))
95 /* Is the atom a valid one? */
96 for (i
= 0; i
< ARRAY_SIZE(valid_atom
); i
++) {
97 int len
= strlen(valid_atom
[i
].name
);
99 * If the atom name has a colon, strip it and everything after
100 * it off - it specifies the format for this entry, and
101 * shouldn't be used for checking against the valid_atom
104 const char *formatp
= strchr(sp
, ':');
105 if (!formatp
|| ep
< formatp
)
107 if (len
== formatp
- sp
&& !memcmp(valid_atom
[i
].name
, sp
, len
))
111 if (ARRAY_SIZE(valid_atom
) <= i
)
112 die("unknown field name: %.*s", (int)(ep
-atom
), atom
);
114 /* Add it in, including the deref prefix */
117 REALLOC_ARRAY(used_atom
, used_atom_cnt
);
118 REALLOC_ARRAY(used_atom_type
, used_atom_cnt
);
119 used_atom
[at
] = xmemdupz(atom
, ep
- atom
);
120 used_atom_type
[at
] = valid_atom
[i
].cmp_type
;
123 if (!strcmp(used_atom
[at
], "symref"))
129 * In a format string, find the next occurrence of %(atom).
131 static const char *find_next(const char *cp
)
136 * %( is the start of an atom;
137 * %% is a quoted per-cent.
141 else if (cp
[1] == '%')
142 cp
++; /* skip over two % */
143 /* otherwise this is a singleton, literal % */
151 * Make sure the format string is well formed, and parse out
154 int verify_ref_format(const char *format
)
158 need_color_reset_at_eol
= 0;
159 for (cp
= format
; *cp
&& (sp
= find_next(cp
)); ) {
160 const char *color
, *ep
= strchr(sp
, ')');
164 return error("malformed format string %s", sp
);
165 /* sp points at "%(" and ep points at the closing ")" */
166 at
= parse_ref_filter_atom(sp
+ 2, ep
);
169 if (skip_prefix(used_atom
[at
], "color:", &color
))
170 need_color_reset_at_eol
= !!strcmp(color
, "reset");
176 * Given an object name, read the object data and size, and return a
177 * "struct object". If the object data we are returning is also borrowed
178 * by the "struct object" representation, set *eaten as well---it is a
179 * signal from parse_object_buffer to us not to free the buffer.
181 static void *get_obj(const unsigned char *sha1
, struct object
**obj
, unsigned long *sz
, int *eaten
)
183 enum object_type type
;
184 void *buf
= read_sha1_file(sha1
, &type
, sz
);
187 *obj
= parse_object_buffer(sha1
, type
, *sz
, buf
, eaten
);
193 static int grab_objectname(const char *name
, const unsigned char *sha1
,
194 struct atom_value
*v
)
196 if (!strcmp(name
, "objectname")) {
197 char *s
= xmalloc(41);
198 strcpy(s
, sha1_to_hex(sha1
));
202 if (!strcmp(name
, "objectname:short")) {
203 v
->s
= xstrdup(find_unique_abbrev(sha1
, DEFAULT_ABBREV
));
209 /* See grab_values */
210 static void grab_common_values(struct atom_value
*val
, int deref
, struct object
*obj
, void *buf
, unsigned long sz
)
214 for (i
= 0; i
< used_atom_cnt
; i
++) {
215 const char *name
= used_atom
[i
];
216 struct atom_value
*v
= &val
[i
];
217 if (!!deref
!= (*name
== '*'))
221 if (!strcmp(name
, "objecttype"))
222 v
->s
= typename(obj
->type
);
223 else if (!strcmp(name
, "objectsize")) {
224 char *s
= xmalloc(40);
225 sprintf(s
, "%lu", sz
);
230 grab_objectname(name
, obj
->sha1
, v
);
234 /* See grab_values */
235 static void grab_tag_values(struct atom_value
*val
, int deref
, struct object
*obj
, void *buf
, unsigned long sz
)
238 struct tag
*tag
= (struct tag
*) obj
;
240 for (i
= 0; i
< used_atom_cnt
; i
++) {
241 const char *name
= used_atom
[i
];
242 struct atom_value
*v
= &val
[i
];
243 if (!!deref
!= (*name
== '*'))
247 if (!strcmp(name
, "tag"))
249 else if (!strcmp(name
, "type") && tag
->tagged
)
250 v
->s
= typename(tag
->tagged
->type
);
251 else if (!strcmp(name
, "object") && tag
->tagged
) {
252 char *s
= xmalloc(41);
253 strcpy(s
, sha1_to_hex(tag
->tagged
->sha1
));
259 /* See grab_values */
260 static void grab_commit_values(struct atom_value
*val
, int deref
, struct object
*obj
, void *buf
, unsigned long sz
)
263 struct commit
*commit
= (struct commit
*) obj
;
265 for (i
= 0; i
< used_atom_cnt
; i
++) {
266 const char *name
= used_atom
[i
];
267 struct atom_value
*v
= &val
[i
];
268 if (!!deref
!= (*name
== '*'))
272 if (!strcmp(name
, "tree")) {
273 char *s
= xmalloc(41);
274 strcpy(s
, sha1_to_hex(commit
->tree
->object
.sha1
));
277 if (!strcmp(name
, "numparent")) {
278 char *s
= xmalloc(40);
279 v
->ul
= commit_list_count(commit
->parents
);
280 sprintf(s
, "%lu", v
->ul
);
283 else if (!strcmp(name
, "parent")) {
284 int num
= commit_list_count(commit
->parents
);
286 struct commit_list
*parents
;
287 char *s
= xmalloc(41 * num
+ 1);
289 for (i
= 0, parents
= commit
->parents
;
291 parents
= parents
->next
, i
= i
+ 41) {
292 struct commit
*parent
= parents
->item
;
293 strcpy(s
+i
, sha1_to_hex(parent
->object
.sha1
));
303 static const char *find_wholine(const char *who
, int wholen
, const char *buf
, unsigned long sz
)
307 if (!strncmp(buf
, who
, wholen
) &&
309 return buf
+ wholen
+ 1;
310 eol
= strchr(buf
, '\n');
315 return ""; /* end of header */
321 static const char *copy_line(const char *buf
)
323 const char *eol
= strchrnul(buf
, '\n');
324 return xmemdupz(buf
, eol
- buf
);
327 static const char *copy_name(const char *buf
)
330 for (cp
= buf
; *cp
&& *cp
!= '\n'; cp
++) {
331 if (!strncmp(cp
, " <", 2))
332 return xmemdupz(buf
, cp
- buf
);
337 static const char *copy_email(const char *buf
)
339 const char *email
= strchr(buf
, '<');
343 eoemail
= strchr(email
, '>');
346 return xmemdupz(email
, eoemail
+ 1 - email
);
349 static char *copy_subject(const char *buf
, unsigned long len
)
351 char *r
= xmemdupz(buf
, len
);
354 for (i
= 0; i
< len
; i
++)
361 static void grab_date(const char *buf
, struct atom_value
*v
, const char *atomname
)
363 const char *eoemail
= strstr(buf
, "> ");
365 unsigned long timestamp
;
367 enum date_mode date_mode
= DATE_NORMAL
;
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_ref_filter_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
) {
379 date_mode
= parse_date_format(formatp
);
384 timestamp
= strtoul(eoemail
+ 2, &zone
, 10);
385 if (timestamp
== ULONG_MAX
)
387 tz
= strtol(zone
, NULL
, 10);
388 if ((tz
== LONG_MIN
|| tz
== LONG_MAX
) && errno
== ERANGE
)
390 v
->s
= xstrdup(show_date(timestamp
, tz
, date_mode
));
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
)
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
== '*'))
412 if (strncmp(who
, name
, wholen
))
414 if (name
[wholen
] != 0 &&
415 strcmp(name
+ wholen
, "name") &&
416 strcmp(name
+ wholen
, "email") &&
417 !starts_with(name
+ wholen
, "date"))
420 wholine
= find_wholine(who
, wholen
, buf
, sz
);
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 (starts_with(name
+ wholen
, "date"))
430 grab_date(wholine
, v
, name
);
434 * For a tag or a commit object, if "creator" or "creatordate" is
435 * requested, do something special.
437 if (strcmp(who
, "tagger") && strcmp(who
, "committer"))
438 return; /* "author" for commit object is not wanted */
440 wholine
= find_wholine(who
, wholen
, buf
, sz
);
443 for (i
= 0; i
< used_atom_cnt
; i
++) {
444 const char *name
= used_atom
[i
];
445 struct atom_value
*v
= &val
[i
];
446 if (!!deref
!= (*name
== '*'))
451 if (starts_with(name
, "creatordate"))
452 grab_date(wholine
, v
, name
);
453 else if (!strcmp(name
, "creator"))
454 v
->s
= copy_line(wholine
);
458 static void find_subpos(const char *buf
, unsigned long sz
,
459 const char **sub
, unsigned long *sublen
,
460 const char **body
, unsigned long *bodylen
,
461 unsigned long *nonsiglen
,
462 const char **sig
, unsigned long *siglen
)
465 /* skip past header until we hit empty line */
466 while (*buf
&& *buf
!= '\n') {
467 eol
= strchrnul(buf
, '\n');
472 /* skip any empty lines */
476 /* parse signature first; we might not even have a subject line */
477 *sig
= buf
+ parse_signature(buf
, strlen(buf
));
478 *siglen
= strlen(*sig
);
480 /* subject is first non-empty line */
482 /* subject goes to first empty line */
483 while (buf
< *sig
&& *buf
&& *buf
!= '\n') {
484 eol
= strchrnul(buf
, '\n');
489 *sublen
= buf
- *sub
;
490 /* drop trailing newline, if present */
491 if (*sublen
&& (*sub
)[*sublen
- 1] == '\n')
494 /* skip any empty lines */
498 *bodylen
= strlen(buf
);
499 *nonsiglen
= *sig
- buf
;
502 /* See grab_values */
503 static void grab_sub_body_contents(struct atom_value
*val
, int deref
, struct object
*obj
, void *buf
, unsigned long sz
)
506 const char *subpos
= NULL
, *bodypos
= NULL
, *sigpos
= NULL
;
507 unsigned long sublen
= 0, bodylen
= 0, nonsiglen
= 0, siglen
= 0;
509 for (i
= 0; i
< used_atom_cnt
; i
++) {
510 const char *name
= used_atom
[i
];
511 struct atom_value
*v
= &val
[i
];
512 if (!!deref
!= (*name
== '*'))
516 if (strcmp(name
, "subject") &&
517 strcmp(name
, "body") &&
518 strcmp(name
, "contents") &&
519 strcmp(name
, "contents:subject") &&
520 strcmp(name
, "contents:body") &&
521 strcmp(name
, "contents:signature"))
526 &bodypos
, &bodylen
, &nonsiglen
,
529 if (!strcmp(name
, "subject"))
530 v
->s
= copy_subject(subpos
, sublen
);
531 else if (!strcmp(name
, "contents:subject"))
532 v
->s
= copy_subject(subpos
, sublen
);
533 else if (!strcmp(name
, "body"))
534 v
->s
= xmemdupz(bodypos
, bodylen
);
535 else if (!strcmp(name
, "contents:body"))
536 v
->s
= xmemdupz(bodypos
, nonsiglen
);
537 else if (!strcmp(name
, "contents:signature"))
538 v
->s
= xmemdupz(sigpos
, siglen
);
539 else if (!strcmp(name
, "contents"))
540 v
->s
= xstrdup(subpos
);
545 * We want to have empty print-string for field requests
546 * that do not apply (e.g. "authordate" for a tag object)
548 static void fill_missing_values(struct atom_value
*val
)
551 for (i
= 0; i
< used_atom_cnt
; i
++) {
552 struct atom_value
*v
= &val
[i
];
559 * val is a list of atom_value to hold returned values. Extract
560 * the values for atoms in used_atom array out of (obj, buf, sz).
561 * when deref is false, (obj, buf, sz) is the object that is
562 * pointed at by the ref itself; otherwise it is the object the
563 * ref (which is a tag) refers to.
565 static void grab_values(struct atom_value
*val
, int deref
, struct object
*obj
, void *buf
, unsigned long sz
)
567 grab_common_values(val
, deref
, obj
, buf
, sz
);
570 grab_tag_values(val
, deref
, obj
, buf
, sz
);
571 grab_sub_body_contents(val
, deref
, obj
, buf
, sz
);
572 grab_person("tagger", val
, deref
, obj
, buf
, sz
);
575 grab_commit_values(val
, deref
, obj
, buf
, sz
);
576 grab_sub_body_contents(val
, deref
, obj
, buf
, sz
);
577 grab_person("author", val
, deref
, obj
, buf
, sz
);
578 grab_person("committer", val
, deref
, obj
, buf
, sz
);
581 /* grab_tree_values(val, deref, obj, buf, sz); */
584 /* grab_blob_values(val, deref, obj, buf, sz); */
587 die("Eh? Object of type %d?", obj
->type
);
591 static inline char *copy_advance(char *dst
, const char *src
)
599 * Parse the object referred by ref, and grab needed value.
601 static void populate_value(struct ref_array_item
*ref
)
607 const unsigned char *tagged
;
609 ref
->value
= xcalloc(used_atom_cnt
, sizeof(struct atom_value
));
611 if (need_symref
&& (ref
->flag
& REF_ISSYMREF
) && !ref
->symref
) {
612 unsigned char unused1
[20];
613 ref
->symref
= resolve_refdup(ref
->refname
, RESOLVE_REF_READING
,
619 /* Fill in specials first */
620 for (i
= 0; i
< used_atom_cnt
; i
++) {
621 const char *name
= used_atom
[i
];
622 struct atom_value
*v
= &ref
->value
[i
];
626 struct branch
*branch
= NULL
;
633 if (starts_with(name
, "refname"))
634 refname
= ref
->refname
;
635 else if (starts_with(name
, "symref"))
636 refname
= ref
->symref
? ref
->symref
: "";
637 else if (starts_with(name
, "upstream")) {
638 const char *branch_name
;
639 /* only local branches may have an upstream */
640 if (!skip_prefix(ref
->refname
, "refs/heads/",
643 branch
= branch_get(branch_name
);
645 refname
= branch_get_upstream(branch
, NULL
);
648 } else if (starts_with(name
, "push")) {
649 const char *branch_name
;
650 if (!skip_prefix(ref
->refname
, "refs/heads/",
653 branch
= branch_get(branch_name
);
655 refname
= branch_get_push(branch
, NULL
);
658 } else if (starts_with(name
, "color:")) {
659 char color
[COLOR_MAXLEN
] = "";
661 if (color_parse(name
+ 6, color
) < 0)
662 die(_("unable to parse format"));
663 v
->s
= xstrdup(color
);
665 } else if (!strcmp(name
, "flag")) {
666 char buf
[256], *cp
= buf
;
667 if (ref
->flag
& REF_ISSYMREF
)
668 cp
= copy_advance(cp
, ",symref");
669 if (ref
->flag
& REF_ISPACKED
)
670 cp
= copy_advance(cp
, ",packed");
675 v
->s
= xstrdup(buf
+ 1);
678 } else if (!deref
&& grab_objectname(name
, ref
->objectname
, v
)) {
680 } else if (!strcmp(name
, "HEAD")) {
682 unsigned char sha1
[20];
684 head
= resolve_ref_unsafe("HEAD", RESOLVE_REF_READING
,
686 if (!strcmp(ref
->refname
, head
))
694 formatp
= strchr(name
, ':');
696 int num_ours
, num_theirs
;
699 if (!strcmp(formatp
, "short"))
700 refname
= shorten_unambiguous_ref(refname
,
701 warn_ambiguous_refs
);
702 else if (!strcmp(formatp
, "track") &&
703 (starts_with(name
, "upstream") ||
704 starts_with(name
, "push"))) {
707 if (stat_tracking_info(branch
, &num_ours
,
711 if (!num_ours
&& !num_theirs
)
713 else if (!num_ours
) {
714 sprintf(buf
, "[behind %d]", num_theirs
);
716 } else if (!num_theirs
) {
717 sprintf(buf
, "[ahead %d]", num_ours
);
720 sprintf(buf
, "[ahead %d, behind %d]",
721 num_ours
, num_theirs
);
725 } else if (!strcmp(formatp
, "trackshort") &&
726 (starts_with(name
, "upstream") ||
727 starts_with(name
, "push"))) {
730 if (stat_tracking_info(branch
, &num_ours
,
734 if (!num_ours
&& !num_theirs
)
738 else if (!num_theirs
)
744 die("unknown %.*s format %s",
745 (int)(formatp
- name
), name
, formatp
);
751 int len
= strlen(refname
);
752 char *s
= xmalloc(len
+ 4);
753 sprintf(s
, "%s^{}", refname
);
758 for (i
= 0; i
< used_atom_cnt
; i
++) {
759 struct atom_value
*v
= &ref
->value
[i
];
766 buf
= get_obj(ref
->objectname
, &obj
, &size
, &eaten
);
768 die("missing object %s for %s",
769 sha1_to_hex(ref
->objectname
), ref
->refname
);
771 die("parse_object_buffer failed on %s for %s",
772 sha1_to_hex(ref
->objectname
), ref
->refname
);
774 grab_values(ref
->value
, 0, obj
, buf
, size
);
779 * If there is no atom that wants to know about tagged
780 * object, we are done.
782 if (!need_tagged
|| (obj
->type
!= OBJ_TAG
))
786 * If it is a tag object, see if we use a value that derefs
787 * the object, and if we do grab the object it refers to.
789 tagged
= ((struct tag
*)obj
)->tagged
->sha1
;
792 * NEEDSWORK: This derefs tag only once, which
793 * is good to deal with chains of trust, but
794 * is not consistent with what deref_tag() does
795 * which peels the onion to the core.
797 buf
= get_obj(tagged
, &obj
, &size
, &eaten
);
799 die("missing object %s for %s",
800 sha1_to_hex(tagged
), ref
->refname
);
802 die("parse_object_buffer failed on %s for %s",
803 sha1_to_hex(tagged
), ref
->refname
);
804 grab_values(ref
->value
, 1, obj
, buf
, size
);
810 * Given a ref, return the value for the atom. This lazily gets value
811 * out of the object by calling populate value.
813 static void get_ref_atom_value(struct ref_array_item
*ref
, int atom
, struct atom_value
**v
)
817 fill_missing_values(ref
->value
);
819 *v
= &ref
->value
[atom
];
823 * Return 1 if the refname matches one of the patterns, otherwise 0.
824 * A pattern can be path prefix (e.g. a refname "refs/heads/master"
825 * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
826 * matches "refs/heads/m*",too).
828 static int match_name_as_path(const char **pattern
, const char *refname
)
830 int namelen
= strlen(refname
);
831 for (; *pattern
; pattern
++) {
832 const char *p
= *pattern
;
833 int plen
= strlen(p
);
835 if ((plen
<= namelen
) &&
836 !strncmp(refname
, p
, plen
) &&
837 (refname
[plen
] == '\0' ||
838 refname
[plen
] == '/' ||
841 if (!wildmatch(p
, refname
, WM_PATHNAME
, NULL
))
847 /* Allocate space for a new ref_array_item and copy the objectname and flag to it */
848 static struct ref_array_item
*new_ref_array_item(const char *refname
,
849 const unsigned char *objectname
,
852 struct ref_array_item
*ref
= xcalloc(1, sizeof(struct ref_array_item
));
853 ref
->refname
= xstrdup(refname
);
854 hashcpy(ref
->objectname
, objectname
);
861 * A call-back given to for_each_ref(). Filter refs and keep them for
862 * later object processing.
864 int ref_filter_handler(const char *refname
, const struct object_id
*oid
, int flag
, void *cb_data
)
866 struct ref_filter_cbdata
*ref_cbdata
= cb_data
;
867 struct ref_filter
*filter
= &ref_cbdata
->filter
;
868 struct ref_array_item
*ref
;
870 if (flag
& REF_BAD_NAME
) {
871 warning("ignoring ref with broken name %s", refname
);
875 if (*filter
->name_patterns
&& !match_name_as_path(filter
->name_patterns
, refname
))
879 * We do not open the object yet; sort may only need refname
880 * to do its job and the resulting list may yet to be pruned
883 ref
= new_ref_array_item(refname
, oid
->hash
, flag
);
885 REALLOC_ARRAY(ref_cbdata
->array
.items
, ref_cbdata
->array
.nr
+ 1);
886 ref_cbdata
->array
.items
[ref_cbdata
->array
.nr
++] = ref
;
890 /* Free memory allocated for a ref_array_item */
891 static void free_array_item(struct ref_array_item
*item
)
893 free((char *)item
->symref
);
898 /* Free all memory allocated for ref_array */
899 void ref_array_clear(struct ref_array
*array
)
903 for (i
= 0; i
< array
->nr
; i
++)
904 free_array_item(array
->items
[i
]);
907 array
->nr
= array
->alloc
= 0;
910 static int cmp_ref_sorting(struct ref_sorting
*s
, struct ref_array_item
*a
, struct ref_array_item
*b
)
912 struct atom_value
*va
, *vb
;
914 cmp_type cmp_type
= used_atom_type
[s
->atom
];
916 get_ref_atom_value(a
, s
->atom
, &va
);
917 get_ref_atom_value(b
, s
->atom
, &vb
);
920 cmp
= strcmp(va
->s
, vb
->s
);
925 else if (va
->ul
== vb
->ul
)
931 return (s
->reverse
) ? -cmp
: cmp
;
934 static struct ref_sorting
*ref_sorting
;
935 static int compare_refs(const void *a_
, const void *b_
)
937 struct ref_array_item
*a
= *((struct ref_array_item
**)a_
);
938 struct ref_array_item
*b
= *((struct ref_array_item
**)b_
);
939 struct ref_sorting
*s
;
941 for (s
= ref_sorting
; s
; s
= s
->next
) {
942 int cmp
= cmp_ref_sorting(s
, a
, b
);
949 void ref_array_sort(struct ref_sorting
*sorting
, struct ref_array
*array
)
951 ref_sorting
= sorting
;
952 qsort(array
->items
, array
->nr
, sizeof(struct ref_array_item
*), compare_refs
);
955 static void print_value(struct atom_value
*v
, int quote_style
)
957 struct strbuf sb
= STRBUF_INIT
;
958 switch (quote_style
) {
963 sq_quote_buf(&sb
, v
->s
);
966 perl_quote_buf(&sb
, v
->s
);
969 python_quote_buf(&sb
, v
->s
);
972 tcl_quote_buf(&sb
, v
->s
);
975 if (quote_style
!= QUOTE_NONE
) {
976 fputs(sb
.buf
, stdout
);
981 static int hex1(char ch
)
983 if ('0' <= ch
&& ch
<= '9')
985 else if ('a' <= ch
&& ch
<= 'f')
986 return ch
- 'a' + 10;
987 else if ('A' <= ch
&& ch
<= 'F')
988 return ch
- 'A' + 10;
991 static int hex2(const char *cp
)
994 return (hex1(cp
[0]) << 4) | hex1(cp
[1]);
999 static void emit(const char *cp
, const char *ep
)
1001 while (*cp
&& (!ep
|| cp
< ep
)) {
1006 int ch
= hex2(cp
+ 1);
1019 void show_ref_array_item(struct ref_array_item
*info
, const char *format
, int quote_style
)
1021 const char *cp
, *sp
, *ep
;
1023 for (cp
= format
; *cp
&& (sp
= find_next(cp
)); cp
= ep
+ 1) {
1024 struct atom_value
*atomv
;
1026 ep
= strchr(sp
, ')');
1029 get_ref_atom_value(info
, parse_ref_filter_atom(sp
+ 2, ep
), &atomv
);
1030 print_value(atomv
, quote_style
);
1033 sp
= cp
+ strlen(cp
);
1036 if (need_color_reset_at_eol
) {
1037 struct atom_value resetv
;
1038 char color
[COLOR_MAXLEN
] = "";
1040 if (color_parse("reset", color
) < 0)
1041 die("BUG: couldn't parse 'reset' as a color");
1043 print_value(&resetv
, quote_style
);
1048 /* If no sorting option is given, use refname to sort as default */
1049 struct ref_sorting
*ref_default_sorting(void)
1051 static const char cstr_name
[] = "refname";
1053 struct ref_sorting
*sorting
= xcalloc(1, sizeof(*sorting
));
1055 sorting
->next
= NULL
;
1056 sorting
->atom
= parse_ref_filter_atom(cstr_name
, cstr_name
+ strlen(cstr_name
));
1060 int parse_opt_ref_sorting(const struct option
*opt
, const char *arg
, int unset
)
1062 struct ref_sorting
**sorting_tail
= opt
->value
;
1063 struct ref_sorting
*s
;
1066 if (!arg
) /* should --no-sort void the list ? */
1069 s
= xcalloc(1, sizeof(*s
));
1070 s
->next
= *sorting_tail
;
1078 s
->atom
= parse_ref_filter_atom(arg
, arg
+len
);
1082 static char const * const for_each_ref_usage
[] = {
1083 N_("git for-each-ref [<options>] [<pattern>]"),
1087 int cmd_for_each_ref(int argc
, const char **argv
, const char *prefix
)
1090 const char *format
= "%(objectname) %(objecttype)\t%(refname)";
1091 struct ref_sorting
*sorting
= NULL
, **sorting_tail
= &sorting
;
1092 int maxcount
= 0, quote_style
= 0;
1093 struct ref_filter_cbdata ref_cbdata
;
1095 struct option opts
[] = {
1096 OPT_BIT('s', "shell", "e_style
,
1097 N_("quote placeholders suitably for shells"), QUOTE_SHELL
),
1098 OPT_BIT('p', "perl", "e_style
,
1099 N_("quote placeholders suitably for perl"), QUOTE_PERL
),
1100 OPT_BIT(0 , "python", "e_style
,
1101 N_("quote placeholders suitably for python"), QUOTE_PYTHON
),
1102 OPT_BIT(0 , "tcl", "e_style
,
1103 N_("quote placeholders suitably for Tcl"), QUOTE_TCL
),
1106 OPT_INTEGER( 0 , "count", &maxcount
, N_("show only <n> matched refs")),
1107 OPT_STRING( 0 , "format", &format
, N_("format"), N_("format to use for the output")),
1108 OPT_CALLBACK(0 , "sort", sorting_tail
, N_("key"),
1109 N_("field name to sort on"), &parse_opt_ref_sorting
),
1113 parse_options(argc
, argv
, prefix
, opts
, for_each_ref_usage
, 0);
1115 error("invalid --count argument: `%d'", maxcount
);
1116 usage_with_options(for_each_ref_usage
, opts
);
1118 if (HAS_MULTI_BITS(quote_style
)) {
1119 error("more than one quoting style?");
1120 usage_with_options(for_each_ref_usage
, opts
);
1122 if (verify_ref_format(format
))
1123 usage_with_options(for_each_ref_usage
, opts
);
1126 sorting
= ref_default_sorting();
1128 /* for warn_ambiguous_refs */
1129 git_config(git_default_config
, NULL
);
1131 memset(&ref_cbdata
, 0, sizeof(ref_cbdata
));
1132 ref_cbdata
.filter
.name_patterns
= argv
;
1133 for_each_rawref(ref_filter_handler
, &ref_cbdata
);
1135 ref_array_sort(sorting
, &ref_cbdata
.array
);
1137 if (!maxcount
|| ref_cbdata
.array
.nr
< maxcount
)
1138 maxcount
= ref_cbdata
.array
.nr
;
1139 for (i
= 0; i
< maxcount
; i
++)
1140 show_ref_array_item(ref_cbdata
.array
.items
[i
], format
, quote_style
);
1141 ref_array_clear(&ref_cbdata
.array
);