sequencer: fix "rebase -i --root" corrupting author header timestamp
[gitweb.git] / sequencer.c
index abb6c5dc26c04e21607615326c4d101cd85d5c00..580516959dac54aadec12a24b55d92c680ed090d 100644 (file)
@@ -27,6 +27,7 @@
 #include "worktree.h"
 #include "oidmap.h"
 #include "oidset.h"
+#include "alias.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -650,6 +651,7 @@ static int write_author_script(const char *message)
                        strbuf_addch(&buf, *(message++));
                else
                        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;
@@ -704,14 +706,16 @@ static const char *read_author_ident(struct strbuf *buf)
        const char *keys[] = {
                "GIT_AUTHOR_NAME=", "GIT_AUTHOR_EMAIL=", "GIT_AUTHOR_DATE="
        };
-       char *in, *out, *eol;
-       int i = 0, len;
+       struct strbuf out = STRBUF_INIT;
+       char *in, *eol;
+       const char *val[3];
+       int i = 0;
 
        if (strbuf_read_file(buf, rebase_path_author_script(), 256) <= 0)
                return NULL;
 
        /* dequote values and construct ident line in-place */
-       for (in = out = buf->buf; i < 3 && in - buf->buf < buf->len; i++) {
+       for (in = buf->buf; i < 3 && in - buf->buf < buf->len; i++) {
                if (!skip_prefix(in, keys[i], (const char **)&in)) {
                        warning("could not parse '%s' (looking for '%s'",
                                rebase_path_author_script(), keys[i]);
@@ -720,17 +724,12 @@ static const char *read_author_ident(struct strbuf *buf)
 
                eol = strchrnul(in, '\n');
                *eol = '\0';
-               sq_dequote(in);
-               len = strlen(in);
-
-               if (i > 0) /* separate values by spaces */
-                       *(out++) = ' ';
-               if (i == 1) /* email needs to be surrounded by <...> */
-                       *(out++) = '<';
-               memmove(out, in, len);
-               out += len;
-               if (i == 1) /* email needs to be surrounded by <...> */
-                       *(out++) = '>';
+               if (!sq_dequote(in)) {
+                       warning(_("bad quoting on %s value in '%s'"),
+                               keys[i], rebase_path_author_script());
+                       return NULL;
+               }
+               val[i] = in;
                in = eol + 1;
        }
 
@@ -740,7 +739,9 @@ static const char *read_author_ident(struct strbuf *buf)
                return NULL;
        }
 
-       buf->len = out - buf->buf;
+       strbuf_addstr(&out, fmt_ident(val[0], val[1], val[2], 0));
+       strbuf_swap(buf, &out);
+       strbuf_release(&out);
        return buf->buf;
 }
 
@@ -783,7 +784,7 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
        struct child_process cmd = CHILD_PROCESS_INIT;
        const char *value;
 
-       if (flags & CREATE_ROOT_COMMIT) {
+       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;
@@ -1247,7 +1248,7 @@ static int try_to_commit(struct strbuf *msg, const char *author,
 
        if (!(flags & ALLOW_EMPTY) && !oidcmp(current_head ?
                                              get_commit_tree_oid(current_head) :
-                                             &empty_tree_oid, &tree)) {
+                                             the_hash_algo->empty_tree, &tree)) {
                res = 1; /* run 'git commit' to display error message */
                goto out;
        }
@@ -1639,7 +1640,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                        unborn = 1;
                } else if (unborn)
                        oidcpy(&head, the_hash_algo->empty_tree);
-               if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
+               if (index_differs_from(unborn ? empty_tree_oid_hex() : "HEAD",
                                       NULL, 0))
                        return error_dirty_index(opts);
        }
@@ -3791,7 +3792,7 @@ static const char *label_oid(struct object_id *oid, const char *label,
                                p[i] = save;
                        }
                }
-       } else if (((len = strlen(label)) == GIT_SHA1_RAWSZ &&
+       } else if (((len = strlen(label)) == the_hash_algo->hexsz &&
                    !get_oid_hex(label, &dummy)) ||
                   (len == 1 && *label == '#') ||
                   hashmap_get_from_hash(&state->labels,