Skip to content

Commit f0939a0

Browse files
peffgitster
authored andcommitted
trailer: add interface for iterating over commit trailers
The trailer code knows how to parse out the trailers and re-format them, but there's no easy way to iterate over the trailers (you can use trailer_info, but you have to then do a bunch of extra parsing). Let's add an iteration interface that makes this easy to do. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 92338c4 commit f0939a0

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

trailer.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,3 +1185,39 @@ void format_trailers_from_commit(struct strbuf *out, const char *msg,
11851185
format_trailer_info(out, &info, opts);
11861186
trailer_info_release(&info);
11871187
}
1188+
1189+
void trailer_iterator_init(struct trailer_iterator *iter, const char *msg)
1190+
{
1191+
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1192+
strbuf_init(&iter->key, 0);
1193+
strbuf_init(&iter->val, 0);
1194+
opts.no_divider = 1;
1195+
trailer_info_get(&iter->info, msg, &opts);
1196+
iter->cur = 0;
1197+
}
1198+
1199+
int trailer_iterator_advance(struct trailer_iterator *iter)
1200+
{
1201+
while (iter->cur < iter->info.trailer_nr) {
1202+
char *trailer = iter->info.trailers[iter->cur++];
1203+
int separator_pos = find_separator(trailer, separators);
1204+
1205+
if (separator_pos < 1)
1206+
continue; /* not a real trailer */
1207+
1208+
strbuf_reset(&iter->key);
1209+
strbuf_reset(&iter->val);
1210+
parse_trailer(&iter->key, &iter->val, NULL,
1211+
trailer, separator_pos);
1212+
unfold_value(&iter->val);
1213+
return 1;
1214+
}
1215+
return 0;
1216+
}
1217+
1218+
void trailer_iterator_release(struct trailer_iterator *iter)
1219+
{
1220+
trailer_info_release(&iter->info);
1221+
strbuf_release(&iter->val);
1222+
strbuf_release(&iter->key);
1223+
}

trailer.h

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
#define TRAILER_H
33

44
#include "list.h"
5-
6-
struct strbuf;
5+
#include "strbuf.h"
76

87
enum trailer_where {
98
WHERE_DEFAULT,
@@ -103,4 +102,46 @@ void trailer_info_release(struct trailer_info *info);
103102
void format_trailers_from_commit(struct strbuf *out, const char *msg,
104103
const struct process_trailer_options *opts);
105104

105+
/*
106+
* An interface for iterating over the trailers found in a particular commit
107+
* message. Use like:
108+
*
109+
* struct trailer_iterator iter;
110+
* trailer_iterator_init(&iter, msg);
111+
* while (trailer_iterator_advance(&iter))
112+
* ... do something with iter.key and iter.val ...
113+
* trailer_iterator_release(&iter);
114+
*/
115+
struct trailer_iterator {
116+
struct strbuf key;
117+
struct strbuf val;
118+
119+
/* private */
120+
struct trailer_info info;
121+
size_t cur;
122+
};
123+
124+
/*
125+
* Initialize "iter" in preparation for walking over the trailers in the commit
126+
* message "msg". The "msg" pointer must remain valid until the iterator is
127+
* released.
128+
*
129+
* After initializing, note that key/val will not yet point to any trailer.
130+
* Call advance() to parse the first one (if any).
131+
*/
132+
void trailer_iterator_init(struct trailer_iterator *iter, const char *msg);
133+
134+
/*
135+
* Advance to the next trailer of the iterator. Returns 0 if there is no such
136+
* trailer, and 1 otherwise. The key and value of the trailer can be
137+
* fetched from the iter->key and iter->value fields (which are valid
138+
* only until the next advance).
139+
*/
140+
int trailer_iterator_advance(struct trailer_iterator *iter);
141+
142+
/*
143+
* Release all resources associated with the trailer iteration.
144+
*/
145+
void trailer_iterator_release(struct trailer_iterator *iter);
146+
106147
#endif /* TRAILER_H */

0 commit comments

Comments
 (0)