From: Junio C Hamano Date: Mon, 22 Dec 2014 20:26:23 +0000 (-0800) Subject: Merge branch 'cc/interpret-trailers-more' X-Git-Tag: v2.3.0-rc0~78 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0ed8a4e161c06b82734f5f5268a5b1fb68abb954;p=thirdparty%2Fgit.git Merge branch 'cc/interpret-trailers-more' "git interpret-trailers" learned to properly handle the "Conflicts:" block at the end. * cc/interpret-trailers-more: trailer: add test with an old style conflict block trailer: reuse ignore_non_trailer() to ignore conflict lines commit: make ignore_non_trailer() non static merge & sequencer: turn "Conflicts:" hint into a comment builtin/commit.c: extract ignore_non_trailer() helper function merge & sequencer: unify codepaths that write "Conflicts:" hint builtin/merge.c: drop a parameter that is never used --- 0ed8a4e161c06b82734f5f5268a5b1fb68abb954 diff --cc commit.c index 19cf8f9c67,07d2290d0d..a54cb9a454 --- a/commit.c +++ b/commit.c @@@ -1619,24 -1661,48 +1619,70 @@@ void print_commit_list(struct commit_li } } +const char *find_commit_header(const char *msg, const char *key, size_t *out_len) +{ + int key_len = strlen(key); + const char *line = msg; + + while (line) { + const char *eol = strchrnul(line, '\n'); + + if (line == eol) + return NULL; + + if (eol - line > key_len && + !strncmp(line, key, key_len) && + line[key_len] == ' ') { + *out_len = eol - line - key_len - 1; + return line + key_len + 1; + } + line = *eol ? eol + 1 : NULL; + } + return NULL; +} ++ + /* + * Inspect sb and determine the true "end" of the log message, in + * order to find where to put a new Signed-off-by: line. Ignored are + * trailing comment lines and blank lines, and also the traditional + * "Conflicts:" block that is not commented out, so that we can use + * "git commit -s --amend" on an existing commit that forgot to remove + * it. + * + * Returns the number of bytes from the tail to ignore, to be fed as + * the second parameter to append_signoff(). + */ + int ignore_non_trailer(struct strbuf *sb) + { + int boc = 0; + int bol = 0; + int in_old_conflicts_block = 0; + + while (bol < sb->len) { + char *next_line; + + if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol))) + next_line = sb->buf + sb->len; + else + next_line++; + + if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') { + /* is this the first of the run of comments? */ + if (!boc) + boc = bol; + /* otherwise, it is just continuing */ + } else if (starts_with(sb->buf + bol, "Conflicts:\n")) { + in_old_conflicts_block = 1; + if (!boc) + boc = bol; + } else if (in_old_conflicts_block && sb->buf[bol] == '\t') { + ; /* a pathname in the conflicts block */ + } else if (boc) { + /* the previous was not trailing comment */ + boc = 0; + in_old_conflicts_block = 0; + } + bol = next_line - sb->buf; + } + return boc ? sb->len - boc : 0; + } diff --cc commit.h index bc68ccbe69,f87b392506..cd35ac150a --- a/commit.h +++ b/commit.h @@@ -326,17 -326,9 +326,20 @@@ extern struct commit_extra_header *read extern void free_commit_extra_headers(struct commit_extra_header *extra); +/* + * Search the commit object contents given by "msg" for the header "key". + * Returns a pointer to the start of the header contents, or NULL. The length + * of the header, up to the first newline, is returned via out_len. + * + * Note that some headers (like mergetag) may be multi-line. It is the caller's + * responsibility to parse further in this case! + */ +extern const char *find_commit_header(const char *msg, const char *key, + size_t *out_len); + + /* Find the end of the log message, the right place for a new trailer. */ + extern int ignore_non_trailer(struct strbuf *sb); + typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra, void *cb_data);