diff options
Diffstat (limited to 'sequencer.c')
-rw-r--r-- | sequencer.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/sequencer.c b/sequencer.c index b14e5dc13c..00cefd129e 100644 --- a/sequencer.c +++ b/sequencer.c @@ -30,6 +30,7 @@ #include "oidset.h" #include "commit-slab.h" #include "alias.h" +#include "commit-reach.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" @@ -225,13 +226,16 @@ static const char *get_todo_path(const struct replay_opts *opts) * Returns 3 when sob exists within conforming footer as last entry */ static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob, - int ignore_footer) + size_t ignore_footer) { + struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; struct trailer_info info; - int i; + size_t i; int found_sob = 0, found_sob_last = 0; - trailer_info_get(&info, sb->buf); + opts.no_divider = 1; + + trailer_info_get(&info, sb->buf, &opts); if (info.trailer_start == info.trailer_end) return 0; @@ -639,7 +643,7 @@ missing_author: else if (*message != '\'') strbuf_addch(&buf, *(message++)); else - strbuf_addf(&buf, "'\\\\%c'", *(message++)); + strbuf_addf(&buf, "'\\%c'", *(message++)); strbuf_addstr(&buf, "'\nGIT_AUTHOR_EMAIL='"); while (*message && *message != '\n' && *message != '\r') if (skip_prefix(message, "> ", &message)) @@ -647,19 +651,37 @@ missing_author: else if (*message != '\'') strbuf_addch(&buf, *(message++)); else - strbuf_addf(&buf, "'\\\\%c'", *(message++)); + strbuf_addf(&buf, "'\\%c'", *(message++)); strbuf_addstr(&buf, "'\nGIT_AUTHOR_DATE='@"); while (*message && *message != '\n' && *message != '\r') if (*message != '\'') strbuf_addch(&buf, *(message++)); else - strbuf_addf(&buf, "'\\\\%c'", *(message++)); + strbuf_addf(&buf, "'\\%c'", *(message++)); strbuf_addch(&buf, '\''); res = write_message(buf.buf, buf.len, rebase_path_author_script(), 1); strbuf_release(&buf); return res; } + +/* + * write_author_script() used to fail to terminate the last line with a "'" and + * also escaped "'" incorrectly as "'\\\\''" rather than "'\\''". We check for + * the terminating "'" on the last line to see how "'" has been escaped in case + * git was upgraded while rebase was stopped. + */ +static int quoting_is_broken(const char *s, size_t n) +{ + /* Skip any empty lines in case the file was hand edited */ + while (n > 0 && s[--n] == '\n') + ; /* empty */ + if (n > 0 && s[n] != '\'') + return 1; + + return 0; +} + /* * Read a list of environment variable assignments (such as the author-script * file) into an environment block. Returns -1 on error, 0 otherwise. @@ -667,14 +689,18 @@ missing_author: static int read_env_script(struct argv_array *env) { struct strbuf script = STRBUF_INIT; - int i, count = 0; - char *p, *p2; + int i, count = 0, sq_bug; + const char *p2; + char *p; if (strbuf_read_file(&script, rebase_path_author_script(), 256) <= 0) return -1; - + /* write_author_script() used to quote incorrectly */ + sq_bug = quoting_is_broken(script.buf, script.len); for (p = script.buf; *p; p++) - if (skip_prefix(p, "'\\\\''", (const char **)&p2)) + if (sq_bug && skip_prefix(p, "'\\\\''", &p2)) + strbuf_splice(&script, p - script.buf, p2 - p, "'", 1); + else if (skip_prefix(p, "'\\''", &p2)) strbuf_splice(&script, p - script.buf, p2 - p, "'", 1); else if (*p == '\'') strbuf_splice(&script, p-- - script.buf, 1, "", 0); @@ -798,11 +824,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts, if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) { struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT; - const char *author = is_rebase_i(opts) ? - read_author_ident(&script) : NULL; + const char *author = NULL; struct object_id root_commit, *cache_tree_oid; int res = 0; + if (is_rebase_i(opts)) { + author = read_author_ident(&script); + if (!author) { + strbuf_release(&script); + return -1; + } + } + if (!defmsg) BUG("root commit without message"); @@ -3799,7 +3832,7 @@ int sequencer_pick_revisions(struct replay_opts *opts) return res; } -void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag) +void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag) { unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP; struct strbuf sob = STRBUF_INIT; |