Merge branch 'nd/cherry-pick-quit-fix'
[gitweb.git] / sequencer.c
index f74dafb3259771571a67e6cbeaf22c4129a020d9..65d371c7461c1f8098e0334532ae7804c30f66d6 100644 (file)
@@ -1253,7 +1253,7 @@ static int try_to_commit(struct strbuf *msg, const char *author,
                commit_list_insert(current_head, &parents);
        }
 
-       if (write_cache_as_tree(&tree, 0, NULL)) {
+       if (write_index_as_tree(&tree, &the_index, get_index_file(), 0, NULL)) {
                res = error(_("git write-tree failed to write a tree"));
                goto out;
        }
@@ -1552,13 +1552,13 @@ static int update_squash_messages(enum todo_command command,
                unlink(rebase_path_fixup_msg());
                strbuf_addf(&buf, "\n%c ", comment_line_char);
                strbuf_addf(&buf, _("This is the commit message #%d:"),
-                           ++opts->current_fixup_count);
+                           ++opts->current_fixup_count + 1);
                strbuf_addstr(&buf, "\n\n");
                strbuf_addstr(&buf, body);
        } else if (command == TODO_FIXUP) {
                strbuf_addf(&buf, "\n%c ", comment_line_char);
                strbuf_addf(&buf, _("The commit message #%d will be skipped:"),
-                           ++opts->current_fixup_count);
+                           ++opts->current_fixup_count + 1);
                strbuf_addstr(&buf, "\n\n");
                strbuf_add_commented_lines(&buf, body, strlen(body));
        } else
@@ -1639,7 +1639,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                 * that represents the "current" state for merge-recursive
                 * to work on.
                 */
-               if (write_cache_as_tree(&head, 0, NULL))
+               if (write_index_as_tree(&head, &the_index, get_index_file(), 0, NULL))
                        return error(_("your index file is unmerged."));
        } else {
                unborn = get_oid("HEAD", &head);
@@ -2610,8 +2610,13 @@ static int error_with_patch(struct commit *commit,
        const char *subject, int subject_len,
        struct replay_opts *opts, int exit_code, int to_amend)
 {
-       if (make_patch(commit, opts))
-               return -1;
+       if (commit) {
+               if (make_patch(commit, opts))
+                       return -1;
+       } else if (copy_file(rebase_path_message(),
+                            git_path_merge_msg(the_repository), 0666))
+               return error(_("unable to copy '%s' to '%s'"),
+                            git_path_merge_msg(the_repository), rebase_path_message());
 
        if (to_amend) {
                if (intend_to_amend())
@@ -2626,9 +2631,18 @@ static int error_with_patch(struct commit *commit,
                          "\n"
                          "  git rebase --continue\n"),
                        gpg_sign_opt_quoted(opts));
-       } else if (exit_code)
-               fprintf_ln(stderr, _("Could not apply %s... %.*s"),
-                       short_commit_name(commit), subject_len, subject);
+       } else if (exit_code) {
+               if (commit)
+                       fprintf_ln(stderr, _("Could not apply %s... %.*s"),
+                                  short_commit_name(commit), subject_len, subject);
+               else
+                       /*
+                        * We don't have the hash of the parent so
+                        * just print the line from the todo file.
+                        */
+                       fprintf_ln(stderr, _("Could not merge %.*s"),
+                                  subject_len, subject);
+       }
 
        return exit_code;
 }
@@ -4255,10 +4269,9 @@ int sequencer_add_exec_commands(const char *commands)
 {
        const char *todo_file = rebase_path_todo();
        struct todo_list todo_list = TODO_LIST_INIT;
-       struct todo_item *item;
        struct strbuf *buf = &todo_list.buf;
        size_t offset = 0, commands_len = strlen(commands);
-       int i, first;
+       int i, insert;
 
        if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
                return error(_("could not read '%s'."), todo_file);
@@ -4268,19 +4281,40 @@ int sequencer_add_exec_commands(const char *commands)
                return error(_("unusable todo list: '%s'"), todo_file);
        }
 
-       first = 1;
-       /* insert <commands> before every pick except the first one */
-       for (item = todo_list.items, i = 0; i < todo_list.nr; i++, item++) {
-               if (item->command == TODO_PICK && !first) {
-                       strbuf_insert(buf, item->offset_in_buf + offset,
-                                     commands, commands_len);
+       /*
+        * Insert <commands> after every pick. Here, fixup/squash chains
+        * are considered part of the pick, so we insert the commands *after*
+        * those chains if there are any.
+        */
+       insert = -1;
+       for (i = 0; i < todo_list.nr; i++) {
+               enum todo_command command = todo_list.items[i].command;
+
+               if (insert >= 0) {
+                       /* skip fixup/squash chains */
+                       if (command == TODO_COMMENT)
+                               continue;
+                       else if (is_fixup(command)) {
+                               insert = i + 1;
+                               continue;
+                       }
+                       strbuf_insert(buf,
+                                     todo_list.items[insert].offset_in_buf +
+                                     offset, commands, commands_len);
                        offset += commands_len;
+                       insert = -1;
                }
-               first = 0;
+
+               if (command == TODO_PICK || command == TODO_MERGE)
+                       insert = i + 1;
        }
 
-       /* append final <commands> */
-       strbuf_add(buf, commands, commands_len);
+       /* insert or append final <commands> */
+       if (insert >= 0 && insert < todo_list.nr)
+               strbuf_insert(buf, todo_list.items[insert].offset_in_buf +
+                             offset, commands, commands_len);
+       else if (insert >= 0 || !offset)
+               strbuf_add(buf, commands, commands_len);
 
        i = write_message(buf->buf, buf->len, todo_file, 0);
        todo_list_release(&todo_list);