Skip to content

Commit fe6eb7f

Browse files
peffgitster
authored andcommitted
commit: provide a function to find a header in a buffer
Usually when we parse a commit, we read it line by line and handle each individual line (e.g., parse_commit and parse_commit_header). Sometimes, however, we only care about extracting a single header. Code in this situation is stuck doing an ad-hoc parse of the commit buffer. Let's provide a reusable function to locate a header within the commit. The code is modeled after pretty.c's get_header, which is used to extract the encoding. Since some callers may not have the "struct commit" to go along with the buffer, we drop that parameter. The only thing lost is a warning for truncated commits, but that's OK. This shouldn't happen in practice, and even if it does, there's no particular reason that this function needs to complain about it. It either finds the header it was asked for, or it doesn't (and in the latter case, the caller will typically complain). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 6c4ab27 commit fe6eb7f

File tree

3 files changed

+39
-27
lines changed

3 files changed

+39
-27
lines changed

commit.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,3 +1660,25 @@ void print_commit_list(struct commit_list *list,
16601660
printf(format, sha1_to_hex(list->item->object.sha1));
16611661
}
16621662
}
1663+
1664+
const char *find_commit_header(const char *msg, const char *key, size_t *out_len)
1665+
{
1666+
int key_len = strlen(key);
1667+
const char *line = msg;
1668+
1669+
while (line) {
1670+
const char *eol = strchrnul(line, '\n');
1671+
1672+
if (line == eol)
1673+
return NULL;
1674+
1675+
if (eol - line > key_len &&
1676+
!strncmp(line, key, key_len) &&
1677+
line[key_len] == ' ') {
1678+
*out_len = eol - line - key_len - 1;
1679+
return line + key_len + 1;
1680+
}
1681+
line = *eol ? eol + 1 : NULL;
1682+
}
1683+
return NULL;
1684+
}

commit.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,17 @@ extern struct commit_extra_header *read_commit_extra_headers(struct commit *, co
313313

314314
extern void free_commit_extra_headers(struct commit_extra_header *extra);
315315

316+
/*
317+
* Search the commit object contents given by "msg" for the header "key".
318+
* Returns a pointer to the start of the header contents, or NULL. The length
319+
* of the header, up to the first newline, is returned via out_len.
320+
*
321+
* Note that some headers (like mergetag) may be multi-line. It is the caller's
322+
* responsibility to parse further in this case!
323+
*/
324+
extern const char *find_commit_header(const char *msg, const char *key,
325+
size_t *out_len);
326+
316327
typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
317328
void *cb_data);
318329

pretty.c

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -547,31 +547,11 @@ static void add_merge_info(const struct pretty_print_context *pp,
547547
strbuf_addch(sb, '\n');
548548
}
549549

550-
static char *get_header(const struct commit *commit, const char *msg,
551-
const char *key)
550+
static char *get_header(const char *msg, const char *key)
552551
{
553-
int key_len = strlen(key);
554-
const char *line = msg;
555-
556-
while (line) {
557-
const char *eol = strchrnul(line, '\n'), *next;
558-
559-
if (line == eol)
560-
return NULL;
561-
if (!*eol) {
562-
warning("malformed commit (header is missing newline): %s",
563-
sha1_to_hex(commit->object.sha1));
564-
next = NULL;
565-
} else
566-
next = eol + 1;
567-
if (eol - line > key_len &&
568-
!strncmp(line, key, key_len) &&
569-
line[key_len] == ' ') {
570-
return xmemdupz(line + key_len + 1, eol - line - key_len - 1);
571-
}
572-
line = next;
573-
}
574-
return NULL;
552+
size_t len;
553+
const char *v = find_commit_header(msg, key, &len);
554+
return v ? xmemdupz(v, len) : NULL;
575555
}
576556

577557
static char *replace_encoding_header(char *buf, const char *encoding)
@@ -617,11 +597,10 @@ const char *logmsg_reencode(const struct commit *commit,
617597

618598
if (!output_encoding || !*output_encoding) {
619599
if (commit_encoding)
620-
*commit_encoding =
621-
get_header(commit, msg, "encoding");
600+
*commit_encoding = get_header(msg, "encoding");
622601
return msg;
623602
}
624-
encoding = get_header(commit, msg, "encoding");
603+
encoding = get_header(msg, "encoding");
625604
if (commit_encoding)
626605
*commit_encoding = encoding;
627606
use_encoding = encoding ? encoding : utf8;

0 commit comments

Comments
 (0)