]> git.ipfire.org Git - thirdparty/git.git/blobdiff - trailer.c
Merge branch 'jc/sign-buffer-failure-propagation-fix' into maint-2.43
[thirdparty/git.git] / trailer.c
index e4b08ed267fa9aa0c3c1535b636b70edc21c70cb..3a0710a4583a4a11fa5a87cda88ef6a3d0610870 100644 (file)
--- a/trailer.c
+++ b/trailer.c
@@ -817,28 +817,56 @@ static ssize_t last_line(const char *buf, size_t len)
 }
 
 /*
- * Return the position of the start of the patch or the length of str if there
- * is no patch in the message.
+ * Find the end of the log message as an offset from the start of the input
+ * (where callers of this function are interested in looking for a trailers
+ * block in the same input). We have to consider two categories of content that
+ * can come at the end of the input which we want to ignore (because they don't
+ * belong in the log message):
+ *
+ * (1) the "patch part" which begins with a "---" divider and has patch
+ * information (like the output of git-format-patch), and
+ *
+ * (2) any trailing comment lines, blank lines like in the output of "git
+ * commit -v", or stuff below the "cut" (scissor) line.
+ *
+ * As a formula, the situation looks like this:
+ *
+ *     INPUT = LOG MESSAGE + IGNORED
+ *
+ * where IGNORED can be either of the two categories described above. It may be
+ * that there is nothing to ignore. Now it may be the case that the LOG MESSAGE
+ * contains a trailer block, but that's not the concern of this function.
  */
-static size_t find_patch_start(const char *str)
+static size_t find_end_of_log_message(const char *input, int no_divider)
 {
+       size_t end;
        const char *s;
 
-       for (s = str; *s; s = next_line(s)) {
+       /* Assume the naive end of the input is already what we want. */
+       end = strlen(input);
+
+       if (no_divider)
+               return end;
+
+       /* Optionally skip over any patch part ("---" line and below). */
+       for (s = input; *s; s = next_line(s)) {
                const char *v;
 
-               if (skip_prefix(s, "---", &v) && isspace(*v))
-                       return s - str;
+               if (skip_prefix(s, "---", &v) && isspace(*v)) {
+                       end = s - input;
+                       break;
+               }
        }
 
-       return s - str;
+       /* Skip over other ignorable bits. */
+       return end - ignored_log_message_bytes(input, end);
 }
 
 /*
  * Return the position of the first trailer line or len if there are no
  * trailers.
  */
-static size_t find_trailer_start(const char *buf, size_t len)
+static size_t find_trailer_block_start(const char *buf, size_t len)
 {
        const char *s;
        ssize_t end_of_title, l;
@@ -933,12 +961,6 @@ continue_outer_loop:
        return len;
 }
 
-/* Return the position of the end of the trailers. */
-static size_t find_trailer_end(const char *buf, size_t len)
-{
-       return len - ignore_non_trailer(buf, len);
-}
-
 static int ends_with_blank_line(const char *buf, size_t len)
 {
        ssize_t ll = last_line(buf, len);
@@ -1060,7 +1082,6 @@ void process_trailers(const char *file,
        LIST_HEAD(head);
        struct strbuf sb = STRBUF_INIT;
        struct trailer_info info;
-       size_t trailer_end;
        FILE *outfile = stdout;
 
        ensure_configured();
@@ -1071,11 +1092,10 @@ void process_trailers(const char *file,
                outfile = create_in_place_tempfile(file);
 
        parse_trailers(&info, sb.buf, &head, opts);
-       trailer_end = info.trailer_end - sb.buf;
 
        /* Print the lines before the trailers */
        if (!opts->only_trailers)
-               fwrite(sb.buf, 1, info.trailer_start - sb.buf, outfile);
+               fwrite(sb.buf, 1, info.trailer_block_start, outfile);
 
        if (!opts->only_trailers && !info.blank_line_before_trailer)
                fprintf(outfile, "\n");
@@ -1097,7 +1117,7 @@ void process_trailers(const char *file,
 
        /* Print the lines after the trailers as is */
        if (!opts->only_trailers)
-               fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
+               fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile);
 
        if (opts->in_place)
                if (rename_tempfile(&trailers_tempfile, file))
@@ -1109,7 +1129,7 @@ void process_trailers(const char *file,
 void trailer_info_get(struct trailer_info *info, const char *str,
                      const struct process_trailer_options *opts)
 {
-       int patch_start, trailer_end, trailer_start;
+       size_t end_of_log_message = 0, trailer_block_start = 0;
        struct strbuf **trailer_lines, **ptr;
        char **trailer_strings = NULL;
        size_t nr = 0, alloc = 0;
@@ -1117,16 +1137,11 @@ void trailer_info_get(struct trailer_info *info, const char *str,
 
        ensure_configured();
 
-       if (opts->no_divider)
-               patch_start = strlen(str);
-       else
-               patch_start = find_patch_start(str);
-
-       trailer_end = find_trailer_end(str, patch_start);
-       trailer_start = find_trailer_start(str, trailer_end);
+       end_of_log_message = find_end_of_log_message(str, opts->no_divider);
+       trailer_block_start = find_trailer_block_start(str, end_of_log_message);
 
-       trailer_lines = strbuf_split_buf(str + trailer_start,
-                                        trailer_end - trailer_start,
+       trailer_lines = strbuf_split_buf(str + trailer_block_start,
+                                        end_of_log_message - trailer_block_start,
                                         '\n',
                                         0);
        for (ptr = trailer_lines; *ptr; ptr++) {
@@ -1147,9 +1162,9 @@ void trailer_info_get(struct trailer_info *info, const char *str,
        strbuf_list_free(trailer_lines);
 
        info->blank_line_before_trailer = ends_with_blank_line(str,
-                                                              trailer_start);
-       info->trailer_start = str + trailer_start;
-       info->trailer_end = str + trailer_end;
+                                                              trailer_block_start);
+       info->trailer_block_start = trailer_block_start;
+       info->trailer_block_end = end_of_log_message;
        info->trailers = trailer_strings;
        info->trailer_nr = nr;
 }
@@ -1164,6 +1179,7 @@ void trailer_info_release(struct trailer_info *info)
 
 static void format_trailer_info(struct strbuf *out,
                                const struct trailer_info *info,
+                               const char *msg,
                                const struct process_trailer_options *opts)
 {
        size_t origlen = out->len;
@@ -1173,8 +1189,8 @@ static void format_trailer_info(struct strbuf *out,
        if (!opts->only_trailers && !opts->unfold && !opts->filter &&
            !opts->separator && !opts->key_only && !opts->value_only &&
            !opts->key_value_separator) {
-               strbuf_add(out, info->trailer_start,
-                          info->trailer_end - info->trailer_start);
+               strbuf_add(out, msg + info->trailer_block_start,
+                          info->trailer_block_end - info->trailer_block_start);
                return;
        }
 
@@ -1228,7 +1244,7 @@ void format_trailers_from_commit(struct strbuf *out, const char *msg,
        struct trailer_info info;
 
        trailer_info_get(&info, msg, opts);
-       format_trailer_info(out, &info, opts);
+       format_trailer_info(out, &info, msg, opts);
        trailer_info_release(&info);
 }